• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

React--Redux②(connect函数原理)

武飞扬头像
一如彷徨
帮助1

connect实现原理

  • connect 的作用就是负责连接 ReactRedux
  • connect 底层本质是高阶函数 高阶组件,即 connect 函数接收函数作为参数,首先返回一个函数返回的函数中又返回了组件,大致结构如下:
 // connent.js
 import { PureComponent } from "react";
 import store from '../store';
 /**
  * @param {Function} mapStateToProps 用于映射store中各模块state的数据
  * @param {Function} mapActionToProps 用于映射store中各模块的action
  * @return {Function} 高阶组件
  */
 // 接收函数作为参数
 export function connent(mapStateToProps, mapActionToProps) {
   // 返回函数
   return function(Component) {
     // 该函数返回组件
     return class extends PureComponent {
       render() {
         return <Component {...this.props}/>
       } 
     }
   }
 }

简单封装

  • stateaction 添加到组件的 props
import store from '../store';

export function connent(mapStateToProps, mapActionToProps) {
  return function(Component) {
    return class extends PureComponent {
      render() {
          // mapStateToProps函数:(state) => ({})
          // 这里调用mapStateToProps并传入state,拿到mapStateToProps中映射的数据
          const stateObj = mapStateToProps(store.getState());
          // 同理
          const actionObj = mapActionToProps(store.dispatch)
          // 将state和action添加到组件的props中
          return <Component {...this.props} {...stateObj} {...actionObj}/>
      } 
    }
  }
}
  • 在返回的新组件中监听 state 的变化
import store from '../store';

export function connent(mapStateToProps, mapActionToProps) {
  return function(Component) {
    return class extends PureComponent {
      constructor() {
        super()
        // 拿到映射的state
        this.state = mapStateToProps(store.getState())
      }
      
      componentDidMount() {
        this.unsubcribe = store.subscribe(() => {
          // 因为PureComponent内部会作浅层比较,所以将整个state更新
          this.setState(mapStateToProps(store.getState()))
        })
      }
      
      // 取消监听
      componentWillUnmount() {
        this.unsubcribe()
      }
      
      render() {
        const stateObj = mapStateToProps(store.getState());
        const actionObj = mapActionToProps(store.dispatch)
        return <Component {...this.props} {...stateObj} {...actionObj}/>
      } 
    }
  }
}

解耦store

  • 上面的做法有一点不好的是,假如把这个自定义的 connect 函数发布到 NPM 仓库中,其他人安装后并没有办法使用,因为其他人的 store 路径不一定是 ../store
  • 这是因为 connect 函数和 store 耦合度太高,所以需要将 store 解耦

使用 context 的方式使用 store

  • 使用 React.CreateContextStore 创建一个上下文
 // hoc/StoreContext.js
 import { createContext } from 'react';
 export const StoreContext = createContext();
  • 新建一个入口文件,将 StoreContextconnect 暴露
 // index.js
 export * from './StoreContext';
 export * from './connect'
  • 使用 <StoreContext.Provider>App 根组件进行包裹,共享 store
 import { StoreContext } from './hoc';
 
 <StoreContext.Provider value={store}>
   <App />
 </StoreContext.Provider>
  • connect 函数中获取 store 的方式改为从 this.context 中获取
 // import store from '../store';
 import { StoreContext } from './StoreContext';
 
 // 重写组件的contextType
 static contextType = StoreContext;
 constructor(props, context) { // 拿到当前context
   super(props)
   this.state = mapStateToProps(context.getState())
 }
 // 其他原本的 store 改为 this.context
 // 如store.getState() → this.context.getState()

简单使用

  • 最后在组件中就可以使用自己封装的 connect 函数了,和 react-redux 一致
 import { PureComponent } from 'react';
 import { connect } from '../src/hoc';
 import { addNum } from './store/modules/counter';
 
 class App extends PureComponent {
   render() {
     const { num, addNum } = this.props
     return (
       <div>
         <h2>App Count: {num}</h2>
         <div className='button-box'>
           <button onClick={e => addNum(1)}> 1</button>
           <button onClick={e => addNum(5)}> 5</button>
           <button onClick={e => addNum(10)}> 10</button>
         </div>
       </div>
     )
   }
 }
 const mapStateToProps = (state) => ({
   num: state.counter.num
 })
 
 const mapActionToProps = (dispatch) => ({
   addNum(num) {
     dispatch(addNum(num))
   }
 })
 
 export default connect(mapStateToProps, mapActionToProps)(App)

学新通

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhgbafjg
系列文章
更多 icon
同类精品
更多 icon
继续加载