redux学习笔记
基础方法1、createStore创建redux的store。支持两种形式createStore(reducer, enchancer)其中reducer为Reducer类型enhancere为StoreEnhancercreateStore(reducer, prelaodedState, enhancer),其中prelaodedState为PreloadedState类型如果enhancer为函数则直接返回enhancer(createStore)(reducer, preloadedState)createStore创建时没有指定enhancer时会分发ActionTypes.INIT返回store对象{dispatch, subscribe, getState, replaceReducer}store对象主要有4个方法dispatch(action: A)根据当前状态以及行为执行currentReducer得到新的状态触发监听器function dispatch(action: A) { if (!isPlainObject(action)) { throw new Error( Actions must be plain objects. Instead, the actual type was: ${kindOf( action )}. You may need to add middleware to your store setup to handle dispatching other values, such as redux-thunk to handle dispatching functions. See https://redux.js.org/tutorials/fundamentals/part-4-store#middleware and https://redux.js.org/tutorials/fundamentals/part-6-async-logic#using-the-redux-thunk-middleware for examples. ) } if (typeof action.type undefined) { throw new Error( Actions may not have an undefined type property. You may have misspelled an action type string constant. ) } if (typeof action.type ! string) { throw new Error( Action type property must be a string. Instead, the actual type was: ${kindOf( action.type )}. Value was: ${String(action.type)} (stringified) ) } if (isDispatching) { throw new Error(Reducers may not dispatch actions.) } try { isDispatching true currentState currentReducer(currentState, action) } finally { isDispatching false } const listeners (currentListeners nextListeners) listeners.forEach(listener { listener() }) return action }subscribe(listener: () void)订阅监听者同时返回取消注册function subscribe(listener: () void) { if (typeof listener ! function) { throw new Error( Expected the listener to be a function. Instead, received: ${kindOf( listener )} ) } if (isDispatching) { throw new Error( You may not call store.subscribe() while the reducer is executing. If you would like to be notified after the store has been updated, subscribe from a component and invoke store.getState() in the callback to access the latest state. See https://redux.js.org/api/store#subscribelistener for more details. ) } let isSubscribed true ensureCanMutateNextListeners() const listenerId listenerIdCounter nextListeners.set(listenerId, listener) return function unsubscribe() { if (!isSubscribed) { return } if (isDispatching) { throw new Error( You may not unsubscribe from a store listener while the reducer is executing. See https://redux.js.org/api/store#subscribelistener for more details. ) } isSubscribed false ensureCanMutateNextListeners() nextListeners.delete(listenerId) currentListeners null } }getState(): S获取当前的状态function getState(): S { if (isDispatching) { throw new Error( You may not call store.getState() while the reducer is executing. The reducer has already received the state as an argument. Pass it down from the top reducer instead of reading it from the store. ) } return currentState as S }replaceReducer(nextReducer: ReducerS, A): void替换reducer重新计算状态function replaceReducer(nextReducer: ReducerS, A): void { if (typeof nextReducer ! function) { throw new Error( Expected the nextReducer to be a function. Instead, received: ${kindOf( nextReducer )} ) } currentReducer nextReducer as unknown as ReducerS, A, PreloadedState // This action has a similar effect to ActionTypes.INIT. // Any reducers that existed in both the new and old rootReducer // will receive the previous state. This effectively populates // the new state tree with any relevant data from the old one. dispatch({ type: ActionTypes.REPLACE } as A) }2、applyMiddleware应用redux的中间件对store作功能增强。其返回StoreEnhancer。其实现为function applyMiddleware(...middlewares) { return (createStore) (reducer, preloadedState) { const store createStore(reducer, preloadedState) const middlewareAPI {getState: store.getState, dispatch: (action, ...args) dispatch(action, ...args)} const chain middlewars.map(middleware middleware(middlewareAPI)) dispatch compose(..chain)(store.dispatch) return {...store, dispatch} } } export default function compose(...funcs: Function[]) { if (funcs.length 0) { // infer the argument type so it is usable in inference down the line return T(arg: T) arg } if (funcs.length 1) { return funcs[0] } return funcs.reduce( (a, b) (...args: any) a(b(...args)) ) }在对middlewars遍历得到chains当中的每一项都是二级函数compose是调用chains顺序是从右到左依次调用3、combineReducers合并Reducer,对多个reducer作统一处理返回函数function combination(state:StateFromReducerMapObjecttypeof reducers, action:AnyAction):stateexport type ReducersMapObjectS any, A extends Action AnyAction { [K in keyof S]: ReducerS[K], A }可以理解为S的key作为ReducersMapObject的keyvalue为Reducer的函数export type StateFromReducersMapObjectM M extends ReducersMapObject ? { [P in keyof M]: M[P] extends Reducerinfer S, any ? S : never } : neverStateFromReducersMapObject添加另一个泛型M约束M如果继承ReducersMapObject则走{ [P in keyof M]: M[P] extends Reducerinfer S, any ? S : never }的逻辑否则就是never。{ [P in keyof M]: M[P] extends Reducerinfer S, any ? S : never }为对象key来自M对象里面也就是ReducersMapObject里面传入的S。key对应的value就是需要判断M[P]是否继承自Reducer否则是never。combineReducers函数实现为finalReducerKeys为reducers的状态的key,finalReducers为key对应的reducer,combination函数遍历reducerKey通过reducer计算得到当前key的状态nextStateForKey,统一放到状态对象nextState中通过状态是否有改变返回nextState或者state。function combination( state: StateFromReducersMapObjecttypeof reducers {}, action: AnyAction ) { let hasChanged false const nextState: StateFromReducersMapObjecttypeof reducers {} for (let i 0; i finalReducerKeys.length; i) { const key finalReducerKeys[i] const reducer finalReducers[key] const previousStateForKey state[key] const nextStateForKey reducer(previousStateForKey, action) nextState[key] nextStateForKey hasChanged hasChanged || nextStateForKey ! previousStateForKey } hasChanged hasChanged || finalReducerKeys.length ! Object.keys(state).length return hasChanged ? nextState : state }4、compose函数组合调用。其实现为function compose(...funcs:Function[]) { if (funcs.length 0) { return (arg) arg } if (funcs.length 1) { return funcs[0] } return funcs.reduce((a, b) (...args) a(b(...args))) }5、 MiddlewareMiddlewareAPI接口包含两个方法dispatch和getStateexport interface MiddlewareAPID extends Dispatch Dispatch, S any { dispatch: D getState: () S }Middleware输入为MiddlewareAPI输出为二级函数其类型定义为,export interface Middleware _DispatchExt {}, // TODO: see if this can be used in type definition somehow (cant be removed, as is used to get final dispatch type) S any, D extends Dispatch Dispatch { ( api: MiddlewareAPID, S ): (next: (action: unknown) unknown) (action: unknown) unknown }redux开源中间件redux-thunkredux-promiseredux-composable-fetchredux-sagareact-router-redux将路由状态纳入redux的状态管理将React Router与Redux store绑定import {browserHistory} from react-router; import {syncHistoryWithStore} from react-router-redux; import reducers from project-path/reducers; const store createStore(reducers); const history syncHistoryWithStore(browserHistory, store);用redux方式改变路由import {browserHistory} from react-router; import {routerMiddleware} from react-router-redux; const middleware routerMiddleware(browserHistory); const store createStore(reducers, applyMiddleware(middleware));