实现
我们用2个文件来实现store和connect的逻辑,用2个文件来做测试用例 目录结构如下:
1.2├── connect.js //connect实现3├── index.jsx //测试用例4├── reducer.js //测试用例的reducer5└── store.js //store实现
store实现 store.js
主要实现全局数据仓库,getStore,dispatch,subscribe方法
1// 迷你版redux实现,全局数据仓库构造函数2function createStore(reducers) {3 var state = {};4 var listeners = [];5 var getState = () => state;6 var dispatch = (actionObj) => {7 let [model, action] = actionObj.type.split("/");8 state = reducers[model](state, action);9 listeners.forEach((l) => l());10 };11 var subscribe = (listener) => {12 listeners.push(listener);13 return () => {14 listeners = listeners.filter((l) => l !== listener);15 };16 };17 return {18 getState,19 dispatch,20 subscribe,21 };22}23export default createStore;
connect实现, connect.js
connect实现主要使用了高阶组件HOC
1import React, { useState, useMemo, useReducer } from "react";2import createStore from "./store";3import reducers from "./reducer";45function baseReducer(state, action) {6 return {7 ...state,8 ...action.payload,9 };10}1112//迷你简易版redux-react实现13const ConnectAdvanced = ({ WrappedComponent, actualChildProps }) => {14 const renderedWrappedComponent = useMemo(15 () => <WrappedComponent {...actualChildProps} />,16 [WrappedComponent, actualChildProps]17 );18 return <>{renderedWrappedComponent}</>;19};2021const ConnectFunction = (props) => {22 const { store, mapStateToProps, dispatch, state, component } = props;23 // let [actualProps, setActualProps] = useState(state);24 let [actualProps,dispatchBase] = useReducer(baseReducer,state)25 store.subscribe(function () {26 const storeData = store.getState();27 let state = mapStateToProps(storeData);28 // setActualProps(state);29 dispatchBase({30 type:'save',31 payload:state32 })33 });34 return (35 <ConnectAdvanced36 WrappedComponent={component}37 actualChildProps={{ ...actualProps, dispatch }}38 />39 );40};4142const connect = (mapStateToProps) => {43 var store = window.store44 ? window.store45 : (window.store = createStore(reducers));46 const storeData = store.getState();47 let state = mapStateToProps(storeData);48 let dispatch = store.dispatch;49 return (component) => {50 return () => {51 return (52 <ConnectFunction53 component={component}54 store={store}55 mapStateToProps={mapStateToProps}56 dispatch={dispatch}57 state={state}58 />59 );60 };61 };62};6364export default connect;
reducer实现, reducer.js
全局reducers
1//数据处理器,纯函数2var countReducer = (state = {}, action) => {3 if (!action) return state;4 const { count = 0 } = state;5 console.log(action);6 switch (action) {7 case "INCREMENT":8 return { ...state, count: count + 1 };9 case "DECREMENT":10 return { ...state, count: count - 1 };11 default:12 return { ...state, count };13 }14};15export default {countReducer}
测试用例 index.js
1import React from "react";2import connect from "./connect";34const Page = function (props) {5 const { count = 0, dispatch = () => {} } = props;6 console.log("count", count);7 return (8 <>9 <div id="counter">count:{count}</div>10 <button11 id="addBtn"12 onClick={() => {13 dispatch({ type: "countReducer/INCREMENT" });14 }}15 >16 addBtn17 </button>18 <button19 id="minusBtn"20 onClick={() => {21 dispatch({ type: "countReducer/DECREMENT" });22 }}23 >24 minusBtn25 </button>26 </>27 );28};2930const connectedPage = connect(({ count }) => ({ count }))(Page);31export default connectedPage;