
本文共 3846 字,大约阅读时间需要 12 分钟。
Lesson 34 动手实现 Redux(五):不要问为什么的 reducer
经过了这么多节的优化,我们有了一个很通用的 createStore
:
function createStore (state, stateChanger) { const listeners = [] const subscribe = (listener) => listeners.push(listener) const getState = () => state const dispatch = (action) => { state = stateChanger(state, action) // 覆盖原对象 listeners.forEach((listener) => listener()) } return { getState, dispatch, subscribe }}
它的使用方式是:
let appState = { title: { text: 'React.js 小书', color: 'red', }, content: { text: 'React.js 小书内容', color: 'blue' }}function stateChanger (state, action) { switch (action.type) { case 'UPDATE_TITLE_TEXT': return { ...state, title: { ...state.title, text: action.text } } case 'UPDATE_TITLE_COLOR': return { ...state, title: { ...state.title, color: action.color } } default: return state }}const store = createStore(appState, stateChanger)...
我们再优化一下,其实 appState
和 stateChanger
可以合并到一起去:
function stateChanger (state, action) { if (!state) { return { title: { text: 'React.js 小书', color: 'red', }, content: { text: 'React.js 小书内容', color: 'blue' } } } switch (action.type) { case 'UPDATE_TITLE_TEXT': return { ...state, title: { ...state.title, text: action.text } } case 'UPDATE_TITLE_COLOR': return { ...state, title: { ...state.title, color: action.color } } default: return state }}
stateChanger
现在既充当了获取初始化数据的功能,也充当了生成更新数据的功能。如果有传入 state
就生成更新数据,否则就是初始化数据。这样我们可以优化 createStore
成一个参数,因为 state
和 stateChanger
合并到一起了:
function createStore (stateChanger) { let state = null const listeners = [] const subscribe = (listener) => listeners.push(listener) const getState = () => state const dispatch = (action) => { state = stateChanger(state, action) listeners.forEach((listener) => listener()) } dispatch({ }) // 初始化 state return { getState, dispatch, subscribe }}
createStore
内部的 state
不再通过参数传入,而是一个局部变量 let state = null
。createStore
的最后会手动调用一次 dispatch({})
,dispatch
内部会调用 stateChanger
,这时候的 state
是 null
,所以这次的 dispatch
其实就是初始化数据了。createStore
内部第一次的 dispatch
导致 state
初始化完成,后续外部的 dispatch
就是修改数据的行为了。
我们给 stateChanger
这个玩意起一个通用的名字:reducer
,不要问为什么,它就是个名字而已,修改 createStore
的参数名字:
function createStore (reducer) { let state = null const listeners = [] const subscribe = (listener) => listeners.push(listener) const getState = () => state const dispatch = (action) => { state = reducer(state, action) listeners.forEach((listener) => listener()) } dispatch({ }) // 初始化 state return { getState, dispatch, subscribe }}
这是一个最终形态的 createStore
,它接受的参数叫 reducer
,reducer
是一个函数,细心的朋友会发现,它其实是一个纯函数(Pure Function)。
reducer
createStore
接受一个叫 reducer
的函数作为参数,这个函数规定是一个纯函数,它接受两个参数,一个是 state
,一个是 action
。
如果没有传入 state
或者 state
是 null
,那么它就会返回一个初始化的数据。如果有传入 state
的话,就会根据 action
来“修改“数据,但其实它没有、也规定不能修改 state
,而是要通过上节所说的把修改路径的对象都复制一遍,然后产生一个新的对象返回。如果它不能识别你的 action
,它就不会产生新的数据,而是(在 default
内部)把 state
原封不动地返回。
reducer
是不允许有副作用的。你不能在里面操作 DOM,也不能发 Ajax 请求,更不能直接修改 state
,它要做的仅仅是 —— 初始化和计算新的 state
。
现在我们可以用这个 createStore
来构建不同的 store
了,只要给它传入符合上述的定义的 reducer
即可:
function themeReducer (state, action) { if (!state) return { themeName: 'Red Theme', themeColor: 'red' } switch (action.type) { case 'UPATE_THEME_NAME': return { ...state, themeName: action.themeName } case 'UPATE_THEME_COLOR': return { ...state, themeColor: action.themeColor } default: return state }}const store = createStore(themeReducer)...
当前内容版权归 或其关联方所有,如需对内容或内容相关联开源项目进行关注与资助,请点击 .
最初的起点:
上一篇:
下一篇:
转载地址:https://blog.csdn.net/Mr_zzr/article/details/125797428 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!
发表评论
最新留言
关于作者
