createStore目的: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源码