React-Redux 源码解读(1)

221 阅读2分钟

前言

本片介绍 react-redux 中的 provider api,可以通过学习源码了解设计哲学,从而提高自身。正所谓,不看看源码,怎么敢说你懂呢?🐒

Provider

Provider 是 react-redux 的核心 api 之一,结合 react context api,用于向组件传递状态集。

使用案例
<Provider store={store}>
  <APP />
</Provider>

可见 Provider 也是一个常规的 React 组件,我们向这个组件传入了 store 属性,它的值即为调用 redux 中   creatStore 方法返回的 store。

./Context

import React from "react";

export const ReactReduxContext = React.createContext(null);

export default ReactReduxContext;

Provider 源码

import React, { Component } from "react";
import PropTypes from "prop-types";
// react context, 可以跨组件层级传递状态。
import { ReactReduxContext } from "./Context";

class Provider extends Component {
  // Provider的使用如上例
  constructor(props) {
    super(props);

    const { store } = props;

    this.state = {
      // storeState为redux创建的状态集合,呈🌲树结构的数据对象
      storeState: store.getState(),
      store
    };
  }

  componentDidMount() {
    this._isMounted = true;
    this.subscribe();
  }

  componentWillUnmount() {
    if (this.unsubscribe) this.unsubscribe();

    this._isMounted = false;
  }

  componentDidUpdate(prevProps) {
    if (this.props.store !== prevProps.store) {
      // 组件更新时,有可能传入了新的store。
      // Provider中订阅了redux的状态变化。
      if (this.unsubscribe) this.unsubscribe();

      this.subscribe();
    }
  }

  subscribe() {
    // 订阅props中store的变化。
    const { store } = this.props;
    // 使用redux中的subscibe方法订阅状态变化。
    this.unsubscribe = store.subscribe(() => {
      const newStoreState = store.getState();

      if (!this._isMounted) {
        // 对于provider中数据的更新需要保证组件已经挂载结束。
        return;
      }

      this.setState(providerState => {
        // 如果前后两次状态未发生变化,则无需进行更新。
        if (providerState.storeState === newStoreState) {
          return null;
        }

        return { storeState: newStoreState };
      });
    });

    // 有可能在reder和挂载两个时间点之间dispatch action,需要考虑此种情况
    const postMountStoreState = store.getState();
    if (postMountStoreState !== this.state.storeState) {
      this.setState({ storeState: postMountStoreState });
    }
  }

  render() {
    // context可以传入,默认使用react context
    const Context = this.props.context || ReactReduxContext;
    // provider是整个应用的状态提供者
    return (
      <Context.Provider value={this.state}>
        {this.props.children}
      </Context.Provider>
    );
  }
}

Provider.propTypes = {
  store: PropTypes.shape({
    subscribe: PropTypes.func.isRequired,
    // disptach在其他api中有用
    dispatch: PropTypes.func.isRequired,
    getState: PropTypes.func.isRequired
  }),
  context: PropTypes.object,
  children: PropTypes.any
};

export default Provider;

总结

provider api 通过使用 react context 技术,为应用提供通过 redux 生产的状态集合 store,并在 store 发生更新时,及时更新内部状态。

注意: context api 需要 react 特定版本的支持。⚠️