您的位置:首页 > Web前端

前端进阶-redux源码分析--dispatch如何更新store

2019-03-22 16:28 633 查看

createStore目的:返回新的staste
createStore = (…arguments) => newState

  • 先来看creatStore部分源码
export default function createStore(reducer, preloadedState, enhancer) {

let currentReducer = reducer
let currentState = preloadedState /
let isDispatching = false

export {
dispatch, // 暴露出dispatch方法
subscribe,
getState,
replaceReducer,
[$$observable]: observable
}

}

creteStore函数暴露出 dispatch方法, 来用于更新state,所以能通过store取到dispatch,
下面来看看dispatch如何实现更新state的

  • dispatch方法
// 定义的dispatch方法
function dispatch(action) {
// 如果 action不是一个简单对象,抛出异常
if (!isPlainObject(action)) {
throw new Error(
'Actions must be plain objects. ' +
'Use custom middleware for async actions.'
)
}
// action必须定义type类型,否则报错
if (typeof action.type === 'undefined') {
throw new Error(
'Actions may not have an undefined "type" property. ' +
'Have you misspelled a constant?'
)
}

// reducer内部不允许再次调用dispatch,否则抛出异常
if (isDispatching) {
throw new Error('Reducers may not dispatch actions.')
}

try {
isDispatching = true

// 将dispatch的action传给currentReducer进而更新state

currentState = currentReducer(currentState, action)

} finally {
isDispatching = false
}

const listeners = currentListeners = nextListeners
for (let i = 0; i < listeners.length; i++) {
const listener = listeners[i]
listener()
}

return action
}

从dispatch方法源码可知道,其实就dispatch的action传给了我们自己定义的reducer来处理,然后返回新的newState

  • getState方法
getState = () => {
return currentState
}

combineReducers 如何更新store的

  • reducerA.js
const reducerA = (state = [], action) => {
switch (action.type) {
case 'A':
return [
...state,
{
id: action.id,
text: action.text,
completed: false
}
]

default:
return state
}
}

export default reducer
  • reducerB.js
const reducerA = (state = [], action) => {
case 'B':
return state.map(todo =>
(todo.id === action.id)
? {...todo, completed: !todo.completed}
: todo
)
default:
return state
}
}
  • index.js
import {Provider} from 'react-redux'
import stores from './combineReducer.js'
import {createStore} from 'redux'
const store = createStore(stores)

ReactDOM.render(
<Provider store={store}>
<App/>
</Provider>,
document.getElementById('root')
);

createStore(combineReducer)

这个时候,dispatch(action)等价于下面

// 用的是复合后的reducer来处理action
currentState = combineReducer(currentState, action)

// 如果此时type=A
currentState = combineReducer(currentState, {type:A...})

这个时候actio.type = A ,应该是由reducerA来处理,返回新的state
但是combineReducer是如何根据传入的action ,传给相应reducer来处理了?

看看combineReducer实现就知道了

  • combineReducer.js
import { combineReducers } from 'redux'
import reducerA form './reducerA'
import reducerB form './reducerB'

export const stores = combineReducers({reducerA,reducerB}) //等价于下面

export default function stores(state = {}, action) {
return { // 最终返回一个对象,即newState
reducerA: reducerA(state.reducerA, action),
reducerB: reducerB(state.reducerB, action),
}
}

所以,其实combineReducer将action传给每个reducer,然后每个reducer根据传入的action判断是否有符合的type,然后进而判断是否更新state

当然combineReducer远不止这么简单,他还会判断传入的reducer是否是一个纯函数,是否返回一个对象,如果不符合要求会抛出相应的警告

下一篇文章继续分析combineReducer源码

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: