一、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
};
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
{name}
{age}
{sons}
;
};
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);
};
}