【前端知识】React 基础巩固(三十七)——自定义connect高阶组件

这篇具有很好参考价值的文章主要介绍了【前端知识】React 基础巩固(三十七)——自定义connect高阶组件。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

React 基础巩固(三十七)——自定义connect高阶组件

一、手撸一个自定义connect高阶组件

import { PureComponent } from "react";
import store from "../store";

/**
 * connect的参数:
 * 参数一: 函数
 * 参数二: 函数
 * 返回值: 函数
 */
export default function connect(mapStateToProps, mapDispatchToProps) {
  // 返回一个高阶组件,本质也是函数
  return function (WrapperComponent) {
    class NewComponent extends PureComponent {
      constructor(props) {
        super(props);
        // 将接收到的mapStateToProps赋给state,用于部分值修改时的浅层比较、更新state
        this.state = mapStateToProps(store.getState());
      }
      componentDidMount() {
        this.unsubscribe = store.subscribe(() => {
          this.setState(mapStateToProps(store.getState()));
        });
      }

      componentWillUnmount() {
        this.unsubscribe();
      }

      render() {
        // 将接收到的mapStateToProps、mapDispatchToProps传入要返回的新组件中
        const stateObj = mapStateToProps(store.getState());
        const dispatchObj = mapDispatchToProps(store.dispatch);
        return (
          <WrapperComponent {...this.props} {...stateObj} {...dispatchObj} />
        );
      }
    }
    return NewComponent;
  };
}

二、目前的问题

import store from "../store";

从这行代码可以看到,目前的connect直接引用了上级目录的store,过于依赖目前既定的store,这样不利于复用。假设另一个项目的store所在位置不在上级目录中,则会出现问题。

三、优化上面的丐版connect

为了让所有人都能使用,我们应该把这种“写死”的做法换成让开发者自己传入一个store:

  1. 构建一个StoreContext,用于创建Store的上下文(src/hoc/StoreContext.js):

    import { createContext } from "react";
    
    export const StoreContext = createContext()
    
  2. 当我们在项目的index.js中引入connect时,引入并使用该上下文,让开发者手动传入当前的store(src/index.js):

    import React from "react";
    import ReactDOM from "react-dom/client";
    import { Provider } from "react-redux";
    import { StoreContext } from "./hoc";
    import App from "./App";
    import store from "./store";
    
    const root = ReactDOM.createRoot(document.getElementById("root"));
    root.render(
      // <React.StrictMode>
    
      <Provider store={store}>
        <StoreContext.Provider value={store}>
          <App />
        </StoreContext.Provider>
      </Provider>
      // </React.StrictMode>
    );
    
    
  3. 在connect中,通过 contextType 共享从 Provider 中传入的 store 变量,将原来直接引用的 store 替换成 this.context(hoc/connect.js):

    import { PureComponent } from "react";
    import { StoreContext } from "./StoreContext";
    
    /**
     * connect的参数:
     * 参数一: 函数
     * 参数二: 函数
     * 返回值: 函数
     */
    export function connect(mapStateToProps, mapDispatchToProps) {
      // 返回一个高阶组件,本质也是函数
      return function (WrapperComponent) {
        class NewComponent extends PureComponent {
          constructor(props, context) {
            super(props);
            // 将接收到的mapStateToProps赋给state,用于部分值修改时的浅层比较、更新state
            this.state = mapStateToProps(context.getState());
          }
          componentDidMount() {
            this.unsubscribe = this.context.subscribe(() => {
              this.setState(mapStateToProps(this.context.getState()));
            });
          }
    
          componentWillUnmount() {
            this.unsubscribe();
          }
    
          render() {
            // 将接收到的mapStateToProps、mapDispatchToProps传入要返回的新组件中
            const stateObj = mapStateToProps(this.context.getState());
            const dispatchObj = mapDispatchToProps(this.context.dispatch);
            return (
              <WrapperComponent {...this.props} {...stateObj} {...dispatchObj} />
            );
          }
        }
    
        // 在类组件中,通过 contextType 共享store变量
        NewComponent.contextType = StoreContext
    
        return NewComponent;
      };
    }
    
    
  4. 最后,在hoc中构建index.js,将优化后的connect导出(hoc/index.js):

    export { StoreContext } from "./StoreContext";
    export { connect } from "./connect";
    
    
  5. 在界面中使用现在优化后的connect:

    import React, { PureComponent } from "react";
    import { connect } from "../hoc";
    import { addNumber } from "../store/features/counter";
    
    export class About extends PureComponent {
      render() {
        const { counter } = this.props;
        return (
          <div>
            <h2>About Counter: {counter}</h2>
          </div>
        );
      }
    }
    
    const mapStateToProps = (state) => ({
      counter: state.counter.counter,
    });
    
    const mapDispatchToProps = (dispatch) => ({
      addNumber(num) {
        dispatch(addNumber(num));
      },
    });
    
    export default connect(mapStateToProps, mapDispatchToProps)(About);
    
    
  6. 查看效果,与之前效果一致:

【前端知识】React 基础巩固(三十七)——自定义connect高阶组件,前端知识,React,react.js,前端,javascript文章来源地址https://www.toymoban.com/news/detail-617308.html

到了这里,关于【前端知识】React 基础巩固(三十七)——自定义connect高阶组件的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【前端知识】React 基础巩固(三十三)——Redux的使用详解

    针对 React 基础巩固(三十二) 中的案例,我们希望抽取页面中共有的代码(例如下方的代码),使用高阶组件统一拦截。 为了让react和redux产生联系,安装一款工具 react-redux 使用 react-redux ,在index.js中统一注入store 新建about.js页面,通过 react-redux 引入store 在App.jsx中引入新的

    2024年02月15日
    浏览(39)
  • 【前端知识】React 基础巩固(三十六)——RTK中的异步操作

    引入RTK中的createAsyncThunk,在extraReducers中监听执行状态 在界面中引入所需的异步操作Action 查看运行结果 extraReducer还可以传入一个函数,函数接受一个builder参数: 查看运行结果,与之前的写法结果一致

    2024年02月15日
    浏览(34)
  • 【前端知识】React 基础巩固(三十九)——React-Router的基本使用

    Router中包含了对路径改变的监听,并且会将相应的路径传递给子组件。 Router包括两个API: BrowserRouter使用history模式 HashRouter使用hash模式(路径后面带有#号) 尝试在项目中使用HashRouter: 安装Router 在 index.js 中引入并使用HashRouter Routes:包裹所有的Route,在其中匹配一个路由(

    2024年02月14日
    浏览(40)
  • 【前端知识】React 基础巩固(三十四)——组件中的异步操作及优化

    通过组件的生命周期来完成网络请求,网络请求的异步代码直接放在组件中 通过redux来管理异步网络请求 在store中引入中间件 redux-thunk 构建 fetchHomeMultidataAction ,将原本在组件中的异步请求代码放入到actionCreators.js中 改写原来的category.jsx,派发异步请求的dispatch 查看运行结果

    2024年02月15日
    浏览(47)
  • 【前端知识】React 基础巩固(三十二)——Redux的三大原则、使用流程及实践

    单一数据源 整个应用程序的state被存储在一颗object tree 中,并且这个object tree 只存储在一个store中; Redux并没有强制让我们不能创建多个Store,但是那样做不利于数据维护; 单一的数据源可以让整个应用程序的state变得方便维护、追踪、修改; State是只读的 唯一修改State的方法

    2024年02月15日
    浏览(42)
  • 【前端知识】React 基础巩固(三十一)——store数据的订阅和Redux的优化

    store/index.js test.js redux代码优化: 将派发的action生成过程放到一个actionCreators函数中 将定义的所有actionCreators的函数,放到一个独立的文件中:actionCreators.js actionCreators 和 reducer 函数中使用字符串常量是一致的,所以将常量抽取到一个独立的constants.js文件中 将reducer和默认值(

    2024年02月15日
    浏览(34)
  • 【前端知识】React 基础巩固(三十八)——log、thunk、applyMiddleware中间件的核心代码

    利用Monkey Patching,修改原有的程序逻辑,在调用dispatch的过程中,通过dispatchAndLog实现日志打印功能 redux中利用中间件 redux-thunk 可以让dispatch不不仅能处理对象,还能处理函数 单个调用函数来应用中间件,非常不方便,封装一个函数来合并中间件 在store/index.js中应用上面三个

    2024年02月14日
    浏览(34)
  • 【前端知识】React 基础巩固(四十六)——自定义Hook的应用

    自定义Hook本质上只是一种函数代码逻辑的抽取,严格意义上而言,它并不算React的特性。 实现组件创建/销毁时打印日志 实现Context共享 封装 TokenContext 和 UserContext 两个Context在自定义Hook useUserToken 中,通过使用 userUserToken 同时获取两个Context的内容: 实现获取滚动位置 封装滚

    2024年02月14日
    浏览(31)
  • 【前端知识】React 基础巩固(十三)——列表渲染

    在 React 中没有像 Vue 模块语法中的 v-for 指令,而是需要我们通过 JS 代码的方式组织数据,转成 JSX 在 React 中,展示列表最多的方式就是使用数组的 map 高阶函数 在展示数组前,有时会进行一些处理 过滤一些内容(filter 函数) 截取数组中的一部分内容(slice 函数) 列表中的

    2024年02月10日
    浏览(35)
  • 【前端知识】React 基础巩固(二十八)——StrictMode

    StrictMode 是一个用来突出显示应用程序中潜在问题的工具 与 Fragment 一样,StrictMode 不会渲染任何可见的 UI 为后代出发额外的检测和警告 严格模式检查仅在开发模式下运行,不影响生产构建 严格模式检查什么? 识别不安全的生命周期 使用过时的 ref API 检查意外的副作用 组件

    2024年02月16日
    浏览(33)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包