手写connect

作者: 未路过 | 来源:发表于2022-10-31 14:41 被阅读0次

使用react-redux中的


function mapStateToProps(state) {
  console.log("查看state");
  console.log(state);
  return { count: state.count, personList: state.person };
}

function mapDispatchToProps(dispatch) {
  return {
    increment: (number) => dispatch(addNumber(number)),
    decrement: (number) => dispatch(deNumber(number)),
    asyncIncrement: (number) => dispatch(addNumber(number)),
  };
}

const CountContainer = connect(mapStateToProps, mapDispatchToProps)(Count);

export default CountContainer;

使用的时候
<CountContainer> </CountContainer>

react-redux就做了两件事,connect和provider,实时监测state更新
给组件套了一个壳子,接受了一个store而已。

RTK就是给store套了个壳子。reducer的写法改变,其他没啥变化。

简单实现1
``js
//connect的参数
//参数1:函数
//参数2:函数
//返回值:函数 =》接受一个高阶组件,返回高阶组件
import { PureComponent } from "react";
import store from "../store/store";
export function connect(mapStateToProps, mapDispatchToProps) {
return function (WrapperComponent) {
class NewComponent extends PureComponent {
render() {
const stateObj = mapStateToProps(store.getState());
const dispatchObj = mapDispatchToProps(store.dispatch);

    return (
      <WrapperComponent
        {...this.props}
        {...stateObj}
        {...dispatchObj}
      ></WrapperComponent>
    );
  }
}

return NewComponent;

};
}

问题就是state里面状态改变,也不会重新调用render函数
以前没有react-redcue的时候是使用store.subscribe(()=>{})来监听的,里面
```js
store.subscribe(()=>{
    ReactDOM.render(<App/>,document.getElementById('root'))
})

强制刷新

//connect的参数
//参数1:函数
//参数2:函数
//返回值:函数 =》接受一个高阶组件,返回高阶组件
import { PureComponent } from "react";
import store from "../store/store";
export function connect(mapStateToProps, mapDispatchToProps) {
  return function (WrapperComponent) {
    class NewComponent extends PureComponent {
      componentDidMount() {
        store.subscribe(() => {
          this.forceUpdate();
        });
      }
      render() {
        console.log("newComponent render");
        const stateObj = mapStateToProps(store.getState());
        const dispatchObj = mapDispatchToProps(store.dispatch);

        return (
          <WrapperComponent
            {...this.props}
            {...stateObj}
            {...dispatchObj}
          ></WrapperComponent>
        );
      }
    }

    return NewComponent;
  };
}

使用setstate

//connect的参数
//参数1:函数
//参数2:函数
//返回值:函数 =》接受一个高阶组件,返回高阶组件
import { PureComponent } from "react";
import store from "../store/store";
export function connect(mapStateToProps, mapDispatchToProps) {
  return function (WrapperComponent) {
    class NewComponent extends PureComponent {
      constructor(props, context) {
        super(props);
        this.state = mapStateToProps(store.getState());
      }

      componentDidMount() {
        this.unsubscribe = store.subscribe(() => {
          // this.forceUpdate();
          //没有必要全部刷新。
          //store里面有很多状态,不仅仅是当前使用connect的组件的这个状态,每次其他组件的状态改变,我们的这个组件也要刷新,所以不太好,就是我们的组件中使用的state如果有改变的话,就刷新改组件。也就是mapStateToProps里面使用的state
          this.setState(mapStateToProps(store.getState()));
          //purecomponet浅层拷贝
        });
      }

      componentWillUnmount() {
        this.unsubscribe();
      }
      render() {
        console.log("newComponent render");
        const stateObj = mapStateToProps(store.getState());
        const dispatchObj = mapDispatchToProps(store.dispatch);

        return (
          <WrapperComponent
            {...this.props}
            {...stateObj}
            {...dispatchObj}
          ></WrapperComponent>
        );
      }
    }

    return NewComponent;
  };
}

接下来把store抽离出去
创建
src/hoc/StoreContext.js

import { createContext } from "react";

export const StoreContext = createContext();

创建
src/hoc/index.js

export { StoreContext } from "./StoreContext";
export { connect } from "./connect";

index.js

import React from "react";
import ReactDOM from "react-dom/client";

import App from "./App";
import { Provider } from "react-redux";
import { StoreContext } from "./hoc";
import store from "./store/store";
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
  <Provider store={store}>
    <StoreContext.Provider value={store}>
      <App />
    </StoreContext.Provider>
  </Provider>
);

connect.js

//connect的参数
//参数1:函数
//参数2:函数
//返回值:函数 =》接受一个高阶组件,返回高阶组件
import { PureComponent } from "react";
import { StoreContext } from "./StoreContext";
export function connect(mapStateToProps, mapDispatchToProps) {
  return function (WrapperComponent) {
    class NewComponent extends PureComponent {
      constructor(props, context) {
        //这个context就是store本身
        super(props);
        this.state = mapStateToProps(context.getState());
      }

      componentDidMount() {
        this.unsubscribe = this.context.subscribe(() => {
          // this.forceUpdate();
          //没有必要全部刷新。
          //store里面有很多状态,不仅仅是当前使用connect的组件的这个状态,每次其他组件的状态改变,我们的这个组件也要刷新,所以不太好,就是我们的组件中使用的state如果有改变的话,就刷新改组件。也就是mapStateToProps里面使用的state
          this.setState(mapStateToProps(this.context.getState()));
          //purecomponet浅层拷贝
        });
      }

      componentWillUnmount() {
        this.unsubscribe();
      }
      render() {
        const stateObj = mapStateToProps(this.context.getState());
        const dispatchObj = mapDispatchToProps(this.context.dispatch);

        return (
          <WrapperComponent
            {...this.props}
            {...stateObj}
            {...dispatchObj}
          ></WrapperComponent>
        );
      }
    }

    NewComponent.contextType = StoreContext;

    return NewComponent;
  };
}
image.png

相关文章

网友评论

    本文标题:手写connect

    本文链接:https://www.haomeiwen.com/subject/gstltdtx.html