react-redux实现

89 阅读1分钟

reactRedux就是靠的Context,provider获取到Store通过context传入其子组件。concent是HOC, 从context获取到store里的三个函数来作为mapStateToProps和mapDispatchToProps对应的参数

bindActionCreators

export default function bindActionCreators(creators,dispatch) {
    let obj = {}
   for (let key in creators) {
    if(typeof creators[key] == 'function'){
        let i = creators[key]()
        obj[key] = () => dispatch({...i})
    }
   }
    return obj
}

Provider

import React from 'react'
import { Context } from './context'

export default function Provider(props) {
    const {store,children} = props
  return (
    <>
    <Context.Provider value={store}>{children}</Context.Provider>
    </>
  )
}

connect

import { useContext, useLayoutEffect, useReducer } from "react";
import { bindActionCreators } from "../my-redux";
import { Context } from "./context";
import { useForceUpdate } from "./hook";

export default function connect(mapStateToProps, mapDispatchToProps) {
  return (Component) => {
    return (props) => {
      const store = useContext(Context);
      const { getState, dispatch, subscribe } = store;
      const stateToProps = mapStateToProps(getState(), props);
      let dispatchToProps = { dispatch };
      if (typeof mapDispatchToProps === 'function') {
        dispatchToProps = mapDispatchToProps(dispatch);
      }else if (typeof mapDispatchToProps === 'object'){
        dispatchToProps = bindActionCreators(mapDispatchToProps,dispatch)
      }

    //   const [, forceUpdate] = useReducer((i) => i + 1, 0);
    const forceUpdate = useForceUpdate()
      useLayoutEffect(() => {
        const unSubScribe = subscribe(() => {
          forceUpdate();
        });
        return () => {
          unSubScribe();
        };
      },[subscribe]);

      return (
        <Component
          {...props}
          {...stateToProps}
          {...dispatchToProps}
        ></Component>
      );
    };
  };
}

hook

import { useCallback, useState } from "react"

export function useForceUpdate(){
    const [state,setState] = useState(0)
    const update = () => {
        setState((pre => pre + 1))
    }
    return useCallback(update,[])
}