关于redux:重学reactredux

39次阅读

共计 3356 个字符,预计需要花费 9 分钟才能阅读完成。

一、redux 应用

redux 应用和之前的 useReducer 应用比拟相似(详情请看 重学 react——context/reducer 一文)

// store.ts
import {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.tsx
import 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.tsx
import 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 会有 dispatch
export 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);
    };
}

正文完
 0