前端进阶-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源码
相关文章推荐
- Android进阶——Small源码分析之更新流程详解
- [原创] jQuery源码分析-如何做jQuery源码分析(更新)
- 如何使用androidpn实现android手机消息推送(简单的源码分析)
- 前端测试系列---如何分析页面性能
- Java源码分析:关于 HashMap 1.8 的重大更新
- Java 工具(jmap,jstack)在linux上的源码分析(六) -F 参数 如何读取线程列表
- <util:properties/>加载的配置文件中有中文导致乱码,如何通过分析源码解决问题?
- 史上最全的 Redux 源码分析
- 关于Solr6.3标准分词源码分析一(如何改动源码,达到分词特殊符号的功能)
- 我的Android进阶之旅------>如何将Android源码导入Eclipse中来查看(非常实用)
- Mybatis Mapper接口是如何找到实现类的-源码分析
- asp.net mvc源码分析-Controllerl篇 如何创建Controller实例
- STL源码分析《3》----辅助空间不足时,如何进行归并排序
- 源码分析Android Handler是如何实现线程间通信的
- Asp.net web Api源码分析-如何获取IHttpHandler
- Redux源码分析之createStore
- 【进阶android】ListView源码分析——适配器及观察者模式
- [转] jQuery源码分析-如何做jQuery源码分析
- 从源码分析如何优雅的使用 Kafka 生产者
- React-native 热更新(1) 脚本与图片更新+图片加载源码分析 android部分