react-redux用法及源码解读

react-redux把组件分为UI组件和容器组件。先看图下图:

《react-redux用法及源码解读》

下面让我们带着题目进修一下react-redux:
1. react-redux怎样将store分发到差别组件中?
2. react-redux怎样做到store发生变化, 对应的组件从新render, 也就是说怎样subscribe store?

UI组件(纯组件)

UI组件特性:
  • 只担任衬着UI, 没有逻辑。
  • 没有状况state。
  • 一切数据都由父组件通报, 也就是从props猎取。

容器组件

特性:
  • 担任营业逻辑和数据管理。
  • 带有内部状况, 内部能够运用state。
  • 运用redux的API。

react-redux API诠释

connect()

用于包裹UI组件天生容器组件, 也就是connect衔接的意义。

connect([mapStateToProps], [mapDispatchToProps], [mergeProps], [options]);

// mapStateToProps(state, ownProps?): function, 返回的是Object(stateProps), 该要领将容器组件state映照到UI组件的props, 也就是输入逻辑, 重点是mapStateToProps会定阅store,每当store更新时, 会从新实行, 假如计算出的UI组件的参数发生变化, 就会触发UI组件的从新衬着。state, 代表监听的全局store,也能够说是全局的state, ownProps示意该组件本身照顾的props要领。

// mapDispatchToProps(dispatch, [ownProps]):function/Object, 假如返回的是对象,则对应每一个Action 的函数名, 在UI组件中挪用须要dispatch, 假如返回的是函数,则已被dispatch包裹(能够用bindActionCreators)。 该参数主如果映照用户行动Action, 从UI组件通报出去, 也就是输出逻辑,这里能够用到redux的api bindActionCreators,

// mergeProps(stateProps, dispatchProps, ownProps) 指定传入的UI组件的props, 默许是Object.assign({}, ownProps, stateProps, dispatchProps)

// options: Obejct, 能够进一步定义connect功用, 如定义store的泉源,指定props的一些更新划定规矩等。


// action,js 
...
export const initSelectConcact = (streamConcacts: StreamToConcact): InitSelectConcactAction => ({
    type: LOCAL_CONCACT,
    streamConcacts,
});
export const testFetch = (dispatch) => dispatch(initSelectConcact([]));

// UnreadCards.js
class UnreadCards
...
componentDidMount() {
    this.props.fetchStreamConcact();
}

const mapStateToProps = (state, ownProps) => ({
  users: getUsers(state),
});
const mapDispatchToProps = (dispatch, ownProps) => ({
  fetchStreamConcact: () => testFetch(dispatch),  // 或许以下
  fetchStream: bindActionCreators(initSelectConcact, dispatch)
});
const mergeProps = (stateProps, dispatchProps, ownProps) => {
  console.log('mergeProps', stateProps, dispatchProps, ownProps);
  return Object.assign({}, ownProps, {
    todos: stateProps.todos[ownProps.userId],
    addTodo: (text) => dispatchProps.addTodo(ownProps.userId, text),
  });
};
const options = {
  pure: true,
  storeKey: 'store',
};

export default connect(mapStateToProps, mapDispatchToProps, mergeProps, options)(UnreadCards);
Provider

connect天生容器组件后,须要将是state数据通报到子组件中, 有两种计划:

  1. A -> B -> C组件数据中通报, 能够经由过程props一层层的通报。
  2. A -> B -> C运用React 的 context属性, 将state绑在跟组件A的context中, A下面的一切子组件都能够经由过程context拿到是state。
    所以,Provider运用第二种, 将全局state绑定在跟组件的context上, 所以Provider的平常用法是在最顶层组件。

回复题目:

  • 1.react-redux是经由过程运用React的Context, 将store经由过程顶层组件通报到上下文环境中。源码截图以下:
    《react-redux用法及源码解读》
  • 2.经由上面的API的剖析, 我们相识connect主如果将我们须要的(组件对应的全局state经由过程reducer定义的key,从全局state挑选出来)数据、将store和action对应, merge二者以props情势通报给connect包裹的组件, 而mapStateToProps内部监听了store的变化, 每当store发生变化,对应映照的state也响应变化, 以props 发生变化而update render,看以下源码:
    《react-redux用法及源码解读》
    《react-redux用法及源码解读》
    《react-redux用法及源码解读》

引见一个高阶组件connectWithActions

为防止在connect参数mapDispatchToProps中反复写action, 我将一切Action经由过程要领绑定在props的actions上, 不必每次去映照当前页面所需的action。

import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';

// 一切页面action鸠合
import * as actions from './actions';

// 缓存actions, 不必每次render都从新加载
let cachedActions;

// action经由过程bindActionCreators绑定dispatch,
const bindActions = (dispatch, ownProps) => {
  if (!cachedActions) {
    cachedActions = {
      dispatch,
      actions: bindActionCreators(actions, dispatch),
    };
  }

  return cachedActions;
};

const connectWithActions = (mapStateToProps: MapStateToProps, mergeProps, options) => (
  component,
) => connect(mapStateToProps, bindActions, mergeProps, options)(component);

export default connectWithActions;


// 用法
class HomeScreen extennds Component {

    componentWillMount() {
        this.props.actions.getList();
    }
    ...

}
export default connectWithActions(state => ({
    users: state.users, 
}))(HomeScreen);

—–完—–

参考文章

    原文作者:toringo
    原文地址: https://segmentfault.com/a/1190000017342043
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞