深入理解: 简单实现 redux 和 react-redux
CodeSandbox:easy-redux-app - CodeSandbox
Redux 是一个基于单方向数据流的状态管理, react-redux 的作用帮助 Redux 和 React 建立链接
01 redux
核心原理
createStore
createStore 是整个 redux 的核心原理,其主要的功能就是创建 store , 并暴露getState
,dispatch
,subscribe
方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| export function createStore(reducer) { let state = undefined let listeners = []
dispatch({ type: ActionTypes.INIT })
function getState() { return state }
function dispatch(action) { state = reducer(state, action) listeners.forEach((listener) => listener()) }
function subscribe(listener) { listeners.push(listener) return function unsubscribe() { listeners = listeners.filter((func) => func !== listener) } }
return { getState, dispatch, subscribe, } }
|
中间件
applyMiddleware
applyMiddleware 用于扩展 Redux 添加中间件,Middleware 可以让你包装 store
的 dispatch
方法来达到你想要的目的,其中 compose
方法,可以让多个 middleware 可以被组合到一起使用,形成 middleware 链。常见 middleware 比如说 日志收集器, 崩溃日志收集器等
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| export function applyMiddleware(...middleWares) { return (createStore) => (reducer) => { const store = createStore(reducer) let dispatch = store.dispatch const middlewareAPI = { getState: store.getState, dispatch, } const chain = middleWares.map((middleware) => middleware(middlewareAPI)) dispatch = compose(...chain)(dispatch) return { ...store, dispatch, } } }
function compose(...funcs) { if (funcs.length === 0) { return (args) => args }
if (funcs.length === 1) { return funcs[0] } return funcs.reduce( (a, b) => (...args) => a(b(...args)) ) }
|
合并 reducer 辅助函数
combineReducers
combineReducers 用于合并多个 reducer , 遇到复杂的应用我们需要拆分不同的 reducer ,拆分后的每个函数负责独立管理 state 的一部分。
| export function combineReducers(reducers) { let nextState = {} return function combination(state, action) { Object.entries(reducers).forEach(([key, reducers]) => { nextState[key] = reducers(nextState[key], action) }) return nextState } }
|
02 react-redux
核心原理
Provider
Provider 用于上层组件注入 store ,其原理,就是通过 react createContext
方法,将 store 暴露到上下文 , 以便容器组件可以接收 store
| import React, { createContext } from 'react'
const ReactReduxContext = createContext()
export function Provider({ store, children }) { return ( <ReactReduxContext.Provider value={store}> {children} </ReactReduxContext.Provider> ) }
|
connect
connect 创建容器组件,将接收到 store 通过 props 注入到 Component
组件中,其中 mapStateToProps
, mapDispatchToProps
分别用于映射 state 和 dispatch 对应 action
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| export const connect = (mapStateToProps, mapDispatchToProps) => (Component) => { return class extends React.Component { static contextType = ReactReduxContext; constructor(props) { super(props); this.state = {} } componentDidMount() { const { subscribe, getState,dispatch } = this.context; this.setState({ ...mapStateToProps(getState()), ...mapDispatchToProps(dispatch) }) this.unsubscribe = subscribe(() => { this.setState({ ...mapStateToProps(getState()), ...mapDispatchToProps(dispatch) }) }) } componentWillUnmount() { this.unsubscribe(); } render() { return ( { <Component {...this.props} {...this.state} /> ) } } }
|