「推荐」React 通信之 Redux,看这一篇就能掌握

Java范思哲 2020-03-25 13:44:05 ⋅ 734 阅读

背景

React 组件 componentDidMount 的时候初始化 Model,并监听 Model 的 change 事件,当 Model 发生改变时调用 React 组件的 setState 方法重新 render 整个组件,最后在组件 componentWillUnmount 的时候取消监听并销毁 Model。

第一部分 Redux的出现

存在即合理

下图左侧所示,react单向流动的特性,导致在复杂的状态管理面前,会越来越麻烦。Redux的出现就是为了解决state里面的数据问题。

下图右侧所示,redux维护单一状态库。


Redux三大特性:

1 唯一数据源

2 保持只读状态

3 数据改变只能通过纯函数来执行



第二部分 Redux概念

一、粗略认识

首先回想下,曾经你去图书馆借书的场景+上图右侧树图。

  • 图书馆

  • 询问管理员是否有《西部世界iii》这本书;

  • 管理员查阅库存;

  • 反馈给你,自己网上找资源去;

  • 你去网上找资源。


这个流程其实包含了Redux的整个流程。

询问 + 查阅反馈。即:action + state = new state

有果必有因


二、具体的概念


React-Redux 将所有组件分成两大类:UI 组件(presentational component)和容器组件(container component)。

UI 组件负责 UI 的呈现,容器组件负责管理数据和逻辑

你可能会问,如果一个组件既有 UI 又有业务逻辑,那怎么办?回答是,将它拆分成下面的结构:外面是一个容器组件,里面包了一个UI 组件。前者负责与外部的通信,将数据传给后者,由后者渲染出视图。

React-Redux 规定,所有的 UI 组件都由用户提供,容器组件则是由 React-Redux 自动生成。也就是说,用户负责视觉层,状态管理则是全部交给它。



以上摘录自---阮一峰的网络日志,建议初学者多读几遍。


  • Action: 把数据从应用传到 store 的有效载荷;

  • Store: 保存数据的地方;

  • Dispatcher: view发出Action的唯一办法;

  • Reducer: Store收到Action以后,必须给出一个新的state,这样view才会发生变化。Reducer即根据Action计算state;

  • State: store里面存储的数据。



三、示例代码

Redux一个简单的加数操作,涉及完整的流程。

其中涉及

  • redux各个概念;

  • UI组件 & 容器组件 的相互关系;

  • Provider的使用

import React, { Component } from "react";import PropTypes from "prop-types";import ReactDOM from "react-dom";import { createStore } from "redux";import { Provider, connect } from "react-redux";// 生成组件class Counter extends Component { render() { const { value, onIncreaseClick } = this.props; return ( <div> <span>{value}</span> <button onClick={onIncreaseClick}>Increase</button> </div> ); }}Counter.propTypes = { value: PropTypes.number.isRequired, onIncreaseClick: PropTypes.func.isRequired};// 定义actionconst increaseAction = { type: "increase" };/** * Reducer函数 * @param {*} state 默认值 * @param {*} action 根据action来计算state. */function counter(state = { count: 0 }, action) { const count = state.count; switch (action.type) { case "increase": return { count: count + 1 }; default: return state; }}/** * 创建store -> 需要reducer -> 默认值+action */const store = createStore(counter);/** * 建立一个从(外部的)state对象到(UI 组件的)props对象的映射关系。 * @param {*} state */function mapStateToProps(state) { return { value: state.count };}/** * 建立 UI 组件的参数到store.dispatch方法的映射 * 定义了哪些用户的操作应该当作 Action,传给 Store。 * 它可以是一个函数,也可以是一个对象。 * * 1. 函数: * - 参数: * 可以拿到dispatch和ownProps(容器组件的props对象)两个参数; * - 返回值 * 一个对象,每个键值对都是一个映射,[键名对应函数名] * 定义了 UI 组件的参数怎样发出 Action。 * 2. 对象 * 它的每个键名也是对应 UI 组件的同名参数,键值应该是一个函数, * 会被当作 Action creator ,返回的 Action 会由 Redux 自动发出。 * @param {*} dispatch */function mapDispatchToProps(dispatch) { return { // 同名函数 onIncreaseClick, dispatch 一个action onIncreaseClick: () => dispatch(increaseAction) };}/** * connect 自动生成容器组件,将UI组件[Counter]与[容器组件]即关联起来。 * Counter: UI 组件 * mapStateToProps:输入逻辑:外部的数据(即state对象)如何转换为 UI 组件的参数 * mapDispatchToProps:用户发出的动作如何变为 Action 对象,从 UI 组件传出去。 */const App = connect( mapStateToProps, mapDispatchToProps)(Counter);// React-Redux 提供Provider组件,可以让容器组件拿到state。// Provider在根组件外面包了一层,这样一来,App的所有子组件就默认都可以拿到state了// 原理:React中的context属性,ReactDOM.render( <Provider store={store}> <App /> </Provider>, document.getElementById("root"));

结合下图理解


总结

这个例子中,最外层的Provider利用react-redux中的provider组件,那么究竟provider组件做了什么?为何provider子组件能够或许context属性?

上篇文章利用context进行传值,并未过多的解释说明。


Provider 本身是一个 react 组件,这一点首先要搞清楚。它的实现原理非常简单,利用了 React 的 context 这一特性。文档Context - React, 只要在最外层的组件实现一个 getChildContext 这个方法,返回一个对象,内部的组件都可以通过 this.context 拿到这个对象。所以一个简单的 Provider 实现是这样的:


class Provider extends React.Component { getChildContext() { return { store: this.props.store } } render() { return this.props.children }}// usageconst store = createStore();ReactDOM.render( <Provider store={store}> <App /> </Provider>, document.querySelector('#root'));

那么整个页面的逻辑流程就是:

  1. 创建Store,createStore(), 接受reducers&默认值;

  2. createStore 对每一个reducer进行dispatch一个action.type=@@redux/INTT类型的action,然后返回state默认值;

  3. render()进行渲染,每个子组件通过传入的this.context.store.getState()方法获取state对象+ownProps给mapStateToProps方法,构建props,应用到子组件上;

  4. UI组件触发action, 随即mapDispatchToProps触发相应的action;

  5. strore接收到action进行reduce,得到新的state,然后再调用所有子组件的mapDispatchToProps生成props.

  6. 最后provider进行重新渲染需要更新的组件。

第三部分

react-redux示例--TodoList demo

试着从头到位实现一边,会更加深对本文的理解。鉴于代码太多&上述的理解,应该是没问题的,但不要眼高手低。





感谢

一幅图明白React-Redux的原理

解析:让你弄懂redux原理

https://www.cnblogs.com/nayek/p/12369418.html

https://www.processon.com/view/5db55958e4b0e433944fdc87

https://www.ruanyifeng.com/blog/2016/09/redux_tutorial_part_three_react-redux.html



全部评论: 0

    我有话说:

    「开源资讯」React 17 正式版发布,构建用户界面的 JavaScript 库

    React简介 React(有时叫React.js或ReactJS)是 Facebook 推出的一个为数据提供渲染为 HTML 视图,用来构建用户界面的开源 JavaScript 库。 React

    精品推荐全懂负载均衡了

    随着互联网的发展,业务流量越来越大并且业务逻辑也越来越复杂,单台机器的性能问题以及单点问题凸显了出来,因此需要多台机器来进行性能的水平扩展以及避免单点故障。

    精品推荐:微服务架构下静态数据通用缓存机制

    在分布式系统中,特别是最近很火的微服务架构下,有没有或者总结出一个业务静态数据的通用缓存处理机制或方案,文章将结合一些实际的研发经验,尝试理清其中存在的关键问题以及探寻通用的解决道。

    【总结】前端5大常见设计模式,代码懂!

    用代码示例来掌握前端5大设计模式

    「强烈推荐是我过最接“地气”的代码问题与重构实践

      写这个文章是因为前段时间确实因为公司的业务开发太忙太紧,所有开发都处在于加班赶项目,并且加入的新人较多造成了系列代码不可控的质量问题。 文章针对段时间代码出现的各种各样的问题

    为什么说作为程序员分库分表的必要性一定要掌握

      互联网大厂程序员必须掌握海量数据和高并发问题处理技能,期望进入大厂的程序员一定要仔细! MySQL 分库分表是做什么的? 相信很多程序员对 MySQL 都比较熟悉了,目前国内

    React生命周期&原生通信,挺简单的

    由四张图引发的系列事件。。。。

    精品推荐:无推送,无新闻,无广告,2倍速视频,直播的超强浏览器

    今天给大家推荐款小众却功能强大的应用,款应用不怎么出名,一直很低调,但是却受到众多好评,相对其他大众的浏

    搞对数据库连接池,次从100优化到3ms!阿里架构师都说好

    我在研究HikariCP(一个数据库连接池)时无意间在HikariCP的Github wiki上看到了文章(即前面给出的链接),文章有力地消除了我一直以来的疑虑,完之后感觉神清气爽。故在此

    Node.js 实战--微信支付系列(二)

    接上首先我们下整体上微信小程序的开发流程图

    假期归来,睡前多款软件发布最新版本

    SpringBoot、Element和React UI等多款软件发布新版本

    浅谈Redux中间件的实践

    用户在UI层面触发行为,一个action对象通过store.dispatch派发到Reducer进行触发,接下来Reducer会根据type来更新对应的Store上的状态树,更改后的state会触发

    Java Web实战-代码

    代码美-小小的优化让你的代码Bug更少,执行效率更高

    React UI 库:React Suite 4.0.2 版本更新-多项Bug修复和新手入门

    React Suite 是React 组件库,为后台产品而生。

    推荐款前端数据源管理工具 algeb

    ALGEB 简介 是一个比较抽象的库,开始可能比较难理解。我写它的初衷,是创建可响应的数据请求管理。在传统数据请求中,我们只是把携带ajax代码的堆函数放在一起,这样可以调用接口。但是这种

    「开源推荐」Nginx可视化配置工具—NginxWebUI,小白也可以玩转

    包括http协议转发, tcp协议转发, 反向代理, 负载均衡, ssl证书自动申请、续签、配置等