资讯专栏INFORMATION COLUMN

react-redux用法及源码解读

Zoom / 3018人阅读

摘要:带有内部状态,内部可以使用。代表监听的全局,也可以说是全局的,表示该组件自身携带的方法。回答问题是通过应用的,将通过顶层组件传递到上下文环境中。所有页面集合缓存不用每次都重新加载通过绑定用法完参考文章

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

下面让我们带着问题学习一下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数据传递到子组件中, 有两种方案:

A -> B -> C组件数据中传递, 可以通过props一层层的传递。

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);

-----完-----

参考文章

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/99912.html

相关文章

  • 带着问题看 react-redux 源码实现

    摘要:更新类型及具体内容负责更新数据的具体逻辑。即根据当前及携带的信息合成新的数据。下面带着这些问题深入了解本质上也是高阶组件的一种实现。核心实现声明以被子组件获取。通过的实现,我们可以得到的重要性浅比较的实现由此可以看到的重要性。前言 Redux作为通用的状态管理器,可以搭配任意界面框架。所以并搭配react使用的话就要借助redux官方提供的React绑定库react-redux,以高效灵活的...

    JellyBool 评论0 收藏0
  • 重读redux源码(二)

    摘要:函数组合,科里化的串联结合示例源码,实现也很优雅,对于返回的,将等参数传递进去,然后执行,等待回调异步完成再。对于正常对象则进行下一步。前言 作为前端状态管理器,这个比较跨时代的工具库redux有很多实现和思想值得我们思考。在深入源码之前,我们可以相关注下一些常见问题,这样带着问题去看实现,也能更加清晰的了解。 常见问题 大概看了下主要有这么几个: redux三大原则 这个可以直接参考...

    dingda 评论0 收藏0
  • [源码解读] react-redux

    摘要:本文并不逐行地对源码进行细致分析,不如说是基于以下几个问题,对源码进行大致的扫览。我们已经知道,中,允许用户注册监听器,这些监听器会在每次执行结束后遍历触发。省略一些无关代码其中,是为了在嵌套的中嵌套执行。 react-redux 源码解读 [TOC] 前置知识 阅读本篇文章前,请先确认你是否了解以下知识: react redux 高阶组件 react diff 机制 其中高阶组件...

    Olivia 评论0 收藏0
  • dva系列源码解读

    摘要:介绍概述本次对源码的解读除了传统的从入手外还将引入带入问题读源码的理念,因为只有这样当读完源码之后才会有切身的收获。 介绍 概述 本次对 dva 源码的解读除了传统的从 api 入手外还将引入带入问题读源码的理念,因为只有这样当读完源码之后才会有切身的收获。另外除了 dva 的源码外还会解读一些常用的 dva 插件的源码。 电子书 https://dva-source-docs.net...

    focusj 评论0 收藏0
  • React-redux基础

    摘要:简介创建的函数,返回一个对象,包含等方法合并多个中间件处理,在实际的前调用一系列中间件,类似于绑定和函数式编程中常见的方法,介绍官方提供的绑定库。 前言 在学习了React之后, 紧跟着而来的就是Redux了~ 在系统性的学习一个东西的时候, 了解其背景、设计以及解决了什么问题都是非常必要的。接下来记录的是, 我个人在学习Redux时的一些杂七杂八~ Redux是什么 通俗理解 h...

    jsyzchen 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<