研究状态管理也算不短时间,对状态管理的本原创内容,盗版必究。未经授权,禁止复制转载。质也渐渐有了自己的认识。在状态管理器领域【转载请注明来源】【版权所有,侵权必究】,有两大流派,即以 redux 为代表的【版权所有,侵权必究】【访问 www.tangshuang.net 获取更多精彩内容】 immutable 流派和以 mobx著作权归作者所有,禁止商业用途转载。著作权归作者所有,禁止商业用途转载。 为代表的 mutable 流派。从数据未经授权,禁止复制转载。著作权归作者所有,禁止商业用途转载。流的纯粹性讲,我们更喜欢 immutab本文作者:唐霜,转载请注明出处。【本文受版权保护】le,但从写代码的便捷性讲,我们更喜欢 【关注微信公众号:wwwtangshuangnet】本文作者:唐霜,转载请注明出处。mutable。基于这种主观上的意愿,i【本文首发于唐霜的博客】未经授权,禁止复制转载。mmer 这个工具诞生了。它以极简主义的【访问 www.tangshuang.net 获取更多精彩内容】【版权所有,侵权必究】方式,为我们提供了以 mutable 的转载请注明出处:www.tangshuang.net著作权归作者所有,禁止商业用途转载。形式修改,但得到一个 immutable【版权所有,侵权必究】【本文受版权保护】 的结果的状态操作形式,从代码量上极速降【本文首发于唐霜的博客】【本文首发于唐霜的博客】低工程复杂度。基于 immer,我撰写了【原创内容,转载请注明出处】著作权归作者所有,禁止商业用途转载。新的 react 全局状态管理器 rea著作权归作者所有,禁止商业用途转载。【本文首发于唐霜的博客】ct-immut,源码只有 150 行左【版权所有】唐霜 www.tangshuang.net【原创不易,请尊重版权】右,却完成了 redux, react-转载请注明出处:www.tangshuang.net【原创内容,转载请注明出处】redux 的所有工作,甚至你不需要再考转载请注明出处:www.tangshuang.net未经授权,禁止复制转载。虑 redux-thunk 这类用于异步未经授权,禁止复制转载。【版权所有,侵权必究】操作的第三方库。
本文版权归作者所有,未经授权不得转载。著作权归作者所有,禁止商业用途转载。【版权所有】唐霜 www.tangshuang.net本文作者:唐霜,转载请注明出处。【关注微信公众号:wwwtangshuangnet】和 react-redux 几乎一致的接【版权所有,侵权必究】【未经授权禁止转载】口
原创内容,盗版必究。转载请注明出处:www.tangshuang.net【访问 www.tangshuang.net 获取更多精彩内容】react-redux 已经被反复证明是【版权所有】唐霜 www.tangshuang.net本文版权归作者所有,未经授权不得转载。最被 react 开发者熟知的状态管理器本文版权归作者所有,未经授权不得转载。转载请注明出处:www.tangshuang.net连接工具,因此我所采用的方式和 reac【关注微信公众号:wwwtangshuangnet】原创内容,盗版必究。t-redux 几乎一模一样。让我们来看【原创不易,请尊重版权】【本文受版权保护】看它的最直接的使用方法:
【版权所有,侵权必究】本文作者:唐霜,转载请注明出处。【转载请注明来源】【本文首发于唐霜的博客】【本文首发于唐霜的博客】import { createStore, Provider } from 'react-immut'
const store = createStore({
name: 'timy',
age: 10,
})
export function App() {
return (
<Provider store={store}>
...
</Provider>
)
}
上面就是我们整个应用的骨架代码。和 re【本文首发于唐霜的博客】【原创内容,转载请注明出处】dux 完全不同,我们不需要写一大堆 r【本文首发于唐霜的博客】【原创内容,转载请注明出处】educer 代码,而是只需要将初始状态【版权所有,侵权必究】本文版权归作者所有,未经授权不得转载。传入即可,正是因为如此,我们的代码量瞬间本文作者:唐霜,转载请注明出处。著作权归作者所有,禁止商业用途转载。少了无数行。
【原创内容,转载请注明出处】【转载请注明来源】【访问 www.tangshuang.net 获取更多精彩内容】【未经授权禁止转载】【版权所有】唐霜 www.tangshuang.net在具体组件中,我们也使用 connect【版权所有,侵权必究】原创内容,盗版必究。 进行连接。
【版权所有】唐霜 www.tangshuang.net【未经授权禁止转载】【版权所有】唐霜 www.tangshuang.net原创内容,盗版必究。【版权所有】唐霜 www.tangshuang.netimport { connect } from 'react-immut'
const mapStateToProps = (state) => {
const { name, age } = state
return { name, age }
}
const mapDispatchToProps = (dispatch) => {
// 这里的 dispatch 就和 react-redux 完全不同了
const changeName = (name) => dispatch('name', name)
const changeAge = (age) => dispatch('age', age)
// 和 react-redux 不同,react-immut 不会主动注入 dispatch 到组件中
return { changeName, changeAge }
}
export default connect(mapStateToProps, mapDispatchToProps)(MyComponent)
function MyComponent(props) {
const { name, age, changeName, changeAge } = props
// ...
}
到目前为止从代码层面,几乎极容易理解,没【原创内容,转载请注明出处】【原创内容,转载请注明出处】有任何难度。
【版权所有,侵权必究】转载请注明出处:www.tangshuang.net原创内容,盗版必究。【原创内容,转载请注明出处】神奇的 dispatch 方法本文作者:唐霜,转载请注明出处。
【关注微信公众号:wwwtangshuangnet】【访问 www.tangshuang.net 获取更多精彩内容】【作者:唐霜】【原创内容,转载请注明出处】和 redux 通过 dispatch 本文作者:唐霜,转载请注明出处。【版权所有】唐霜 www.tangshuang.netaction 不同,react-immu【关注微信公众号:wwwtangshuangnet】【关注微信公众号:wwwtangshuangnet】t 的 dispatch 是一个神奇的方原创内容,盗版必究。【本文首发于唐霜的博客】法,它可以让我们实现极简的编程体验。上文【未经授权禁止转载】著作权归作者所有,禁止商业用途转载。红色代码已经见过了 dispatch 的【本文受版权保护】著作权归作者所有,禁止商业用途转载。方便之处。接下来,我们将会看到一些神奇的转载请注明出处:www.tangshuang.net【本文受版权保护】事要发生。
【原创内容,转载请注明出处】本文作者:唐霜,转载请注明出处。【转载请注明来源】【版权所有】唐霜 www.tangshuang.net> dispatch(keyPath, value)
这里的 keyPath 可不是单纯的属性【版权所有】唐霜 www.tangshuang.net未经授权,禁止复制转载。名,而是一个属性路径。我们来看看具体用法【原创内容,转载请注明出处】【原创不易,请尊重版权】:
转载请注明出处:www.tangshuang.net未经授权,禁止复制转载。【作者:唐霜】dispatch('parent.child', 'new value')
dispatch('books[0].title', 'new title')
dispatch(['root', symbol], Symbol())
你看,它的变化形式真是多样。【关注微信公众号:wwwtangshuangnet】
本文作者:唐霜,转载请注明出处。原创内容,盗版必究。本文作者:唐霜,转载请注明出处。原创内容,盗版必究。> dispatch(keyPath, prev => next?)
第二个参数是一个函数,它接收当前值,返回转载请注明出处:www.tangshuang.net【版权所有】唐霜 www.tangshuang.net新值。这就好玩了,我们可以发挥很多想法了转载请注明出处:www.tangshuang.net【原创不易,请尊重版权】。
著作权归作者所有,禁止商业用途转载。【访问 www.tangshuang.net 获取更多精彩内容】著作权归作者所有,禁止商业用途转载。转载请注明出处:www.tangshuang.net未经授权,禁止复制转载。dispatch('name', name => {
return name === 'tomy' ? name : 'gage'
})
dispatch('some', some => {
some.child.name = 'some'
some.child.age = 10
})
不一样的事情终于发生了。这里,红色的代码【本文受版权保护】本文作者:唐霜,转载请注明出处。显得格外刺眼,如果在传统的 immuta未经授权,禁止复制转载。本文版权归作者所有,未经授权不得转载。ble 系统中,我们是不允许这样写的,但【版权所有,侵权必究】【版权所有,侵权必究】是,在 react-immut 中,它是【原创不易,请尊重版权】本文作者:唐霜,转载请注明出处。最好的写法。试着想想,如果放到以前,为了未经授权,禁止复制转载。原创内容,盗版必究。 immutable,你可能必须这样操作【原创内容,转载请注明出处】【作者:唐霜】:
【版权所有】唐霜 www.tangshuang.net【本文受版权保护】原创内容,盗版必究。本文作者:唐霜,转载请注明出处。dispatch('some', some => {
return {
...some,
child: {
...some.child,
name: 'some',
age: 10,
},
}
})
看,多么麻烦。如果再多几层,混杂对象和数【转载请注明来源】【本文受版权保护】组,那会是令人抓狂的一个操作。但是,基于【版权所有,侵权必究】【本文首发于唐霜的博客】 immer,我们只需要像前面的示例代码本文作者:唐霜,转载请注明出处。【本文首发于唐霜的博客】一样写,直接修改对象属性值,就可以了,而本文版权归作者所有,未经授权不得转载。【未经授权禁止转载】且,最终,你得到的状态是 immutab本文版权归作者所有,未经授权不得转载。本文作者:唐霜,转载请注明出处。le 的,这个操作不会带来对象被修改的结著作权归作者所有,禁止商业用途转载。原创内容,盗版必究。果,放心使用吧。
转载请注明出处:www.tangshuang.net【版权所有】唐霜 www.tangshuang.net未经授权,禁止复制转载。【原创不易,请尊重版权】> dispatch(prev => next?)
不传入 keyPath,那么可以直接获得未经授权,禁止复制转载。【本文受版权保护】整个应用的 state。
著作权归作者所有,禁止商业用途转载。本文版权归作者所有,未经授权不得转载。未经授权,禁止复制转载。原创内容,盗版必究。dispatch(state => {
state.name = 'tomy'
})
是否返回 next 是很关键的,如果返回【版权所有】唐霜 www.tangshuang.net【版权所有】唐霜 www.tangshuang.net next,那么会用 next 替换 p转载请注明出处:www.tangshuang.net【原创不易,请尊重版权】rev 的地位,但是必须注意,next 【关注微信公众号:wwwtangshuangnet】著作权归作者所有,禁止商业用途转载。和 prev 的数据类型必须一直,都是 【访问 www.tangshuang.net 获取更多精彩内容】未经授权,禁止复制转载。‘object’转载请注明出处:www.tangshuang.net【版权所有】唐霜 www.tangshuang.net (对象或数组)。而 immer 的最佳未经授权,禁止复制转载。【版权所有】唐霜 www.tangshuang.net实践,反而是不返回任何内容,不返回内容,【版权所有】唐霜 www.tangshuang.net【版权所有】唐霜 www.tangshuang.net恰恰可以让我们更清楚知道,哪些值被修改。
【未经授权禁止转载】【本文受版权保护】【版权所有】唐霜 www.tangshuang.net【转载请注明来源】【访问 www.tangshuang.net 获取更多精彩内容】使用 Hooks本文版权归作者所有,未经授权不得转载。
【原创内容,转载请注明出处】【原创内容,转载请注明出处】【本文首发于唐霜的博客】都 2020 了,hooks 当然不能少【原创内容,转载请注明出处】【未经授权禁止转载】。使用 hooks 方法 useStor【版权所有】唐霜 www.tangshuang.net【未经授权禁止转载】e 可以省略 connect 的步骤,简【版权所有,侵权必究】【原创内容,转载请注明出处】化代码。
【版权所有,侵权必究】【转载请注明来源】本文作者:唐霜,转载请注明出处。【作者:唐霜】【作者:唐霜】import { useStore } from 'react-immut'
function MyComponent() {
const [state, dispatch] = useStore() // 获得整个应用的 state 和 dispatch 方法
}
需要注意的是,useStore 基于 c转载请注明出处:www.tangshuang.net【版权所有】唐霜 www.tangshuang.netontext,也就是说,你必须在 Pro【作者:唐霜】【本文首发于唐霜的博客】vider 内部使用 useStore。本文版权归作者所有,未经授权不得转载。未经授权,禁止复制转载。这样获取全局状态,完全不需要 conne原创内容,盗版必究。【原创内容,转载请注明出处】ct 了,是不是感觉飞起来呢?
未经授权,禁止复制转载。【版权所有,侵权必究】原创内容,盗版必究。原创内容,盗版必究。Combined Store本文版权归作者所有,未经授权不得转载。
转载请注明出处:www.tangshuang.net【关注微信公众号:wwwtangshuangnet】【版权所有】唐霜 www.tangshuang.net很多情况下,我们常常会对我们的状态进行分原创内容,盗版必究。【作者:唐霜】区,每一个独立分区,我们称之为 name【版权所有,侵权必究】【访问 www.tangshuang.net 获取更多精彩内容】space。我们倾向于将关于一个业务组件【原创内容,转载请注明出处】【转载请注明来源】的所有代码文件放在同一个文件夹下面组织,原创内容,盗版必究。【原创不易,请尊重版权】这样有利于我们更好的管理同一个业务组件相著作权归作者所有,禁止商业用途转载。【本文首发于唐霜的博客】关的所有代码。为了方便这种场景,我们提供本文版权归作者所有,未经授权不得转载。【访问 www.tangshuang.net 获取更多精彩内容】了一种 combined store,通【版权所有,侵权必究】【版权所有】唐霜 www.tangshuang.net过 namespace 的方式组织全局状【访问 www.tangshuang.net 获取更多精彩内容】未经授权,禁止复制转载。态。
著作权归作者所有,禁止商业用途转载。【版权所有,侵权必究】【本文首发于唐霜的博客】【转载请注明来源】// components/a-some/store.js
export const state = { // state 是必须的
name: 'Tom',
age: 10,
}
export function changeName(dispatch, name) { // 定义一些方法
dispatch(state => { // 这个 state 指向的是这个局部 state,而非全局 state,也就是说,在该文件内,只能修改该命名空间内的 state,而无法修改其他空间的 state
state.name = name
})
}
export function changeAge(dispatch, age) {
dispatch(state => {
state.age = age
})
}
接下来,我们使用这个定义好的文件【版权所有】唐霜 www.tangshuang.net
【访问 www.tangshuang.net 获取更多精彩内容】本文版权归作者所有,未经授权不得转载。【访问 www.tangshuang.net 获取更多精彩内容】// app.js
import { createStore } from 'react-immut'
import * as Asome from './components/a-some/store.js'
// 传入第二个参数,第二个参数的结构如下
const store = createStore(null, {
Asome, // 使用 'Asome' 作为命名空间名称
// 这里可以引入其他命名空间
})
export default function App() {
return (
<Provider store={store}>
...
</Provider>
)
}
在具体的组件中,通过 key 读取命名空著作权归作者所有,禁止商业用途转载。原创内容,盗版必究。间(本质上和从全局 state 上读取没【本文受版权保护】本文版权归作者所有,未经授权不得转载。有差别)。
【版权所有】唐霜 www.tangshuang.net【原创内容,转载请注明出处】【关注微信公众号:wwwtangshuangnet】著作权归作者所有,禁止商业用途转载。【版权所有】唐霜 www.tangshuang.netfunction MyComponent() {
const [{ name, age }, { changeName, changeAge }] = useStore('Asome')
// ...
}
combine 本质上干了两件事,一是把本文作者:唐霜,转载请注明出处。【版权所有】唐霜 www.tangshuang.net结构化的对象解析出来创建 store,二【本文受版权保护】【访问 www.tangshuang.net 获取更多精彩内容】是解析出来命名空间上的方法,把这些方法添本文版权归作者所有,未经授权不得转载。【版权所有,侵权必究】加到 dispatch 上。虽然 dis转载请注明出处:www.tangshuang.net【原创不易,请尊重版权】patch 是一个函数,但是由于在 js原创内容,盗版必究。【访问 www.tangshuang.net 获取更多精彩内容】 语言中,函数的本质也是对象,所以,可以【本文受版权保护】【本文受版权保护】给函数添加属性,这样,当使用 combi【未经授权禁止转载】未经授权,禁止复制转载。ned store 之后,可以在这个函数著作权归作者所有,禁止商业用途转载。著作权归作者所有,禁止商业用途转载。上增加命名空间属性,让开发者可以方便的读转载请注明出处:www.tangshuang.net【作者:唐霜】取定义好的方法。
著作权归作者所有,禁止商业用途转载。【转载请注明来源】【原创内容,转载请注明出处】【原创内容,转载请注明出处】const mapDispatchToProps = (dispatch) => {
const { changeName, changeAge } = dispatch.Asome
return { changeName, changeAge }
}
异步转载请注明出处:www.tangshuang.net
转载请注明出处:www.tangshuang.net【原创内容,转载请注明出处】【访问 www.tangshuang.net 获取更多精彩内容】和 redux 最大的不同在于,我们没有转载请注明出处:www.tangshuang.net【本文受版权保护】 reducer,因此我们对 state【本文首发于唐霜的博客】未经授权,禁止复制转载。 的操作都是外部实现的,而非 store【本文首发于唐霜的博客】【原创内容,转载请注明出处】 内部定义的。只要我们能调用到 disp【关注微信公众号:wwwtangshuangnet】【转载请注明来源】atch,我们就可以修改 state。因【转载请注明来源】未经授权,禁止复制转载。此,异步操作实在是太简单了。
【转载请注明来源】【未经授权禁止转载】【作者:唐霜】export function saveName(dispatch, name) { fetch('...', { method: 'POST', body: JSON.stringify({ name }) }) .then(res => res.json()) .then(data => { dispatch(state => { state.name = data.name }) }) }
无论在组件内部,还是在 connect 转载请注明出处:www.tangshuang.net【原创内容,转载请注明出处】的 mapDispatchToProps【关注微信公众号:wwwtangshuangnet】转载请注明出处:www.tangshuang.net 函数中,还是在命名空间定义的方法中,我【转载请注明来源】转载请注明出处:www.tangshuang.net们都可以调用 dispatch 来实现这【本文首发于唐霜的博客】【访问 www.tangshuang.net 获取更多精彩内容】个效果。
【未经授权禁止转载】未经授权,禁止复制转载。【关注微信公众号:wwwtangshuangnet】本文版权归作者所有,未经授权不得转载。结束语著作权归作者所有,禁止商业用途转载。
本文作者:唐霜,转载请注明出处。本文版权归作者所有,未经授权不得转载。【版权所有,侵权必究】本文介绍了 react-immut 的用转载请注明出处:www.tangshuang.net著作权归作者所有,禁止商业用途转载。法,它利用 immer 的超能力,实现极【访问 www.tangshuang.net 获取更多精彩内容】【版权所有】唐霜 www.tangshuang.net其方便的全局状态更新,设计上又和 rea【转载请注明来源】【本文受版权保护】ct-redux 相同,让开发者可以没有【版权所有,侵权必究】【转载请注明来源】太大的门槛切换。而且,它的源码只有 15转载请注明出处:www.tangshuang.net著作权归作者所有,禁止商业用途转载。0 行左右,没有复杂的魔法,踏踏实实写的本文版权归作者所有,未经授权不得转载。本文作者:唐霜,转载请注明出处。,你可以在这里【转载请注明来源】读到它的源码。利用 immutable 【作者:唐霜】未经授权,禁止复制转载。的特性,我们可以做任何 redux 能做著作权归作者所有,禁止商业用途转载。【本文受版权保护】的事情,例如时间旅行等。不再需要样板代码未经授权,禁止复制转载。【未经授权禁止转载】,我们为什么还非得要 redux 呢?
转载请注明出处:www.tangshuang.net【关注微信公众号:wwwtangshuangnet】【关注微信公众号:wwwtangshuangnet】未经授权,禁止复制转载。2020-09-04 3265


