博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
react-redux用法及源码解读
阅读量:7080 次
发布时间:2019-06-28

本文共 3586 字,大约阅读时间需要 11 分钟。

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

clipboard.png

下面让我们带着问题学习一下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.jsclass 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通过顶层组件传递到上下文环境中。源码截图如下:
    图片描述
  • 2.经过上面的API的分析, 我们了解connect主要是将我们需要的(组件对应的全局state通过reducer定义的key,从全局state筛选出来)数据、将store和action对应, merge两者以props形式传递给connect包裹的组件, 而mapStateToProps内部监听了store的变化, 每当store发生变化,对应映射的state也相应变化, 以props 发生变化而update render,看如下源码:
    图片描述
    图片描述
    图片描述

介绍一个高阶组件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);

-----完-----

转载地址:http://djvml.baihongyu.com/

你可能感兴趣的文章
SOP 1.6.0 发布,开放平台解决方案项目
查看>>
Java并发编程笔记之AbstractQueuedSynchronizer源码分析
查看>>
AI戒毒?没错,北京开始这么干了
查看>>
第178天:表单验证
查看>>
HTTP配置文件详解(访问控制、虚拟主机、DEFLATE、HTTPS配置
查看>>
数据库分离附加(附日记丢失的处理)
查看>>
开启HDR视觉盛宴:究竟什么视频算得上HDR?
查看>>
阿里云视频点播播放常见问题排查指南
查看>>
Java最全异常讲解
查看>>
Android保持屏幕常亮
查看>>
JS-DOM2级事件对象跨浏览器处理(已封装)
查看>>
用户名和密码校验程序
查看>>
浅析Java RTTI 和 反射的概念
查看>>
Django中用户权限模块
查看>>
Android TransitionDrawable:过渡动画Drawable
查看>>
隐私浏览器 Tor Browser 8.0.7 发布,安全更新版本
查看>>
Veeam发布2016年业绩: 同比增长28%,预订总收入达6.07亿美元
查看>>
慧荣科技发布全球首款商用SD 5.1控制器解决方案
查看>>
spark 计算结果写入mysql 案例及常见问题解决
查看>>
杨博:医疗大数据服务任重道远
查看>>