# react-redux的实现原理

在普通的redux使用过程中,一般在组件内需要以下两个步骤:

  • componentDidMount中进行订阅store中状态的更新
  • 在组件使用dispatch(action)进行异步行为分发
import React, { Component } from 'react'
import { store } from '../redux/store';
import * as action from '../redux/action';

export default class Home extends Component {
    state = {
        num: store.getState()
    }
    componentDidMount() {
        store.subscribe(() => {
            this.setState({ num: store.getState() })
        })
    }
    render() {
        return (
            <div>
                Home---{this.state.num}
                <button onClick={() => { store.dispatch(action.add(1)) }}>点我+1</button>
                <button onClick={() => { store.dispatch(action.del(1)) }}>点我-1</button>
            </div>
        )
    }
}

上面的组件中都会有subscribedispatch的部分。所以我们现在需要把这两个部分提取出来,然后所有组件就都可以进行复用了。

# connect高阶函数:

so我们定义一个connect函数connect(mapStateToProps, mapDispatchToProps)

  • 参数一:里面存放 component 希望使用到的 State 属性;
  • 参数二:里面存放 component 希望使用到的 dispatch动作;
  • 返回值:是一个高阶组件其参数是传入需要连接的组件,返回值是连接后的组件。
import React, { PureComponent } from "react";
import store from '../store';

export default function connect(mapStateToProps,mapDispatchToProps) {
  return function handleMapCpn(WrappedComponent) {
     return class extends PureComponent {
      constructor(props) {
        super(props);

        this.state = {
          storeState: mapStateToProps(store.getState())
        }
      }

      componentDidMount() {
        this.unsubscribe = store.subscribe(() => {
          this.setState({
            storeState: mapStateToProps(store.getState())
          })
        })
      }

      componentWillUnmount() {
        this.unsubscribe();
      }

      render() {
        return <WrappedComponent
                 {...this.props}
                 {...mapStateToProps(store.getState())}
                 {...mapDispatchToProps(store.dispatch)}/>
      }
     }
}

此时我们项目中的任意组件,想要和redux容器进connect连接,就只需要如下操作:

const mapStateToProps = state => {
  return {
    num: state.num
  }
}

const mapDispatchToProps = dispatch => {
  return {
    addNumber: function(number) {
      dispatch(action.add(number));
    }
  }
}

export default connect(mapStateToProps, mapDispatchToProps)(Home);

# context组件传值:

此时我们的Home组件怎么才能使用到store容器中的state状态呢?

我们就开始引入共享context来各组件间传值:

1.在入口文件index.js中使用Provider包裹根组件,传入需要共享的状态容器。

import store from './store';
import { createContext } from 'react';

ReactDOM.render(
  <StoreContext.Provider value={store}>
    <App />
  </StoreContext.Provider>,
  document.getElementById('root')
);
export const StoreContext = createContext();

2.进一步修改connect函数中使用consumer进行包裹使用共享容器store中的状态。

import React, { PureComponent } from "react";

import { StoreContext } from './index';

export default function connect(mapStateToProps, mapDispatchToProps) {
  return function handleMapCpn(WrappedComponent) {
    class ConnectCpn extends PureComponent {
      constructor(props, context) {
        super(props);

        this.state = {
          storeState: mapStateToProps(context.getState())
        }
      }
      componentDidMount() {
        this.unsubscribe = this.context.subscribe(() => {
          this.setState({
            storeState: mapStateToProps(this.context.getState())
          })
        })
      }
      componentWillUnmount() {
        this.unsubscribe();
      }
      render() {
        return <WrappedComponent 
                 {...this.props}
                 {...mapStateToProps(this.context.getState())}
                 {...mapDispatchToProps(this.context.dispatch)} />
      }
    }
    ConnectCpn.contextType = StoreContext;
    //类组件的消费共享context方式,相当于使用consumer包裹
    return ConnectCpn;
  }
}

就可以我们就可以在ConnectCpn组件中对redux中的全局状态容器进行操作,返回对应的Home组件。

Last Updated: 8/1/2021, 1:43:20 PM