一、redux应用
redux应用和之前的useReducer应用比拟相似(详情请看 重学react——context/reducer 一文)
// store.tsimport { createStore, applyMiddleware, combineReducers } from 'redux';import logger from 'redux-logger'; // 中间件import thunk from 'redux-thunk'; // 中间件export interface IState { name: string, age: number, sons: any[]}export const state: IState = { name: 'lihaixing', age: 32, sons: []};export type Action = { type?: string; data?: any;};export function reducer(state: IState | undefined, action: Action) { if (!action.type && !action.data) { return { ...state, ...action }; } switch (action.type) { case 'update': return { ...state, ...action.data }; default: return state; }}// createStore与useReducer相似export const store = createStore(reducer, state, applyMiddleware(logger, thunk));
// contaner.tsximport React, { useReducer } from 'react';// react-redux的作用和react的context相似import {Provider} from 'react-redux'; import { store } from './store';import Com1 from './comp1'import Com2 from './comp2'const IndexView = () => { return <Provider store={store}> <Com1 /> <Com2 /> </Provider>};export default IndexView;
// com1.tsximport React, { useContext } from 'react';import { IState } from './index';// connect和useContext的作用相似import { connect } from 'react-redux';const IndexView = (props: any) => { const {name, age, sons} = props.state; const {update, asyncUpdate} = props; const setAge = () => { // dispatch({type: 'update', data: {age: age + 1}}); update({age: age + 1}); }; const setSons = () => { // setTimeout(()=>{ // update({sons: [...sons, 1]}); // }) asyncUpdate({sons: [...sons, 1]}); }; return <div> {name} <br/> {age} <br/> {sons} <br/> <button onClick={setAge}>按钮age</button> <button onClick={setSons}>按钮sons</button> </div>;};const mapStateToProps = (state: IState) => ({state});const mapDispatchToProps = { update: (data: any) => ({type: 'update', data}), // 异步返回的是函数 asyncUpdate: (data: any) => (dispatch: any) => { setTimeout(() => { dispatch({type: 'update', data}); },1000); }};// 不传第二个参数,props会有dispatchexport default connect(mapStateToProps, mapDispatchToProps)(IndexView);
从上述咱们能够将redux和useReducer/useContext作比照
重学react——context/reducer
二、手写Redux
1、createStore
export function createStore(reducer: any, state: any, enhancer?: any) { if (!!enhancer) { return enhancer(createStore)(reducer, state); } let currentState: any = state; const currentListener: any[] = []; function getState() { return currentState; } function dispatch(action: any) { currentState = reducer(currentState, action); currentListener.forEach((v) => v()); return action; } function subscribe(cb: any) { currentListener.push(cb); } return { getState, dispatch, subscribe };}
2、中间件
export function applyMiddleware(...middlewares: any) { return (createStore: any) => { return (reducer: any, state: any) => { const store = createStore(reducer, state); let dispatch = store.dispatch; const midApi = { getState: store.getState, dispatch: (...arg: any) => dispatch(...arg) }; /** * 太难了,写不上来了 * @type {any[]} */ const chains = middlewares.map((mw: any) => mw(midApi)); // 强化dispatch 按程序执行 dispatch = compose(...chains)(dispatch); console.log(dispatch) return { ...store, dispatch }; }; };}// 聚合函数 f3(f2(f1(arg)))// const f1=(x)=>x;// const f2=(x)=>2*x;// const f3=(x)=>3*x;export function compose(...funcs: any) { if (funcs.length === 1) { return funcs[0]; } return funcs.reduce((left: any, right: any) => (...args: any) => right(left(...args)));}
// 本人写一个中间件function logger({getState, dispatch}: { getState: any, dispatch: any }) { return (dispatch: any) => (action: any) => { console.log(action.type + '执行了'); return dispatch(action); };}function thunk({getState, dispatch}: { getState: any, dispatch: any }) { return (dispatch: any) => (action: any) => { if (typeof action === 'function') { return action(dispatch, getState); } return dispatch(action); };}