学习React有一段时间了,但对于Redux却不是那么理解。网上看了一些文章,现在把对Redux的理解总结如下

从需求出发,看看使用React需要什么

1. React有props和state

props => 父级分发下来的属性

state => 组件内部可以自行管理的状态

React有个特点就是,它没有数据向上回溯的能力,也就是说数据只能单向向下分发,或者自行内部消化

2. 构建的一个React组件内部可能是一个完整的应用, 它自己可以工作的很好。 但是你会发现React根本无法让两个组件互相交流,使用对方的数据.  这个时候如果不通过DOM沟通(也就是React体制内), 解决的唯一办法就是提升state, 将state放到共有的父组件中来管理,再作为props分发回子组件.

3. 如果子组件需要改变父组件的state,也就是说,要从下往上改变state,有没有办法呢

唯一的办法,只能是通过onClick触发父组件声明好的回调,也就是说,父组件提前声明好函数或者方法作为契约描述自己的state将如何变化,再将它同样作为属性props交给子组件使用

这样就是一个模式, 数据总是单向从顶层向下分发,只有子组件回调在概念上可以回到state顶层影响数据,这样state在一定程度上是响应式的

4. 针对上面的情况和理解,最容易的开发方法,就是把所有的state集中放到所有组件顶层,然后分发给所有组件

5.  为了更好的管理所有的state, 我们可能就需要一个库来作为更专业的顶层state分发给所有的React应用,  这个就是Redux了。

根据上面的需求,我们结合Redux的三大要素来一起看看:

a. 需要回调通知state(等同于回调函数) => action

b. 需要根据回调处理(等同于父级方法) => reducer

c. 需要state(等同于总状态) => store

上面的action, reducer 和 store就是Redux的三大要素  (Redux三剑客: action, reducer, store)

a. action是纯声明式的数据结构,只提供事件的所有要素,不提供逻辑

b. reducer是一个匹配函数,action的发送是针对全局发送. 所有的reducer都可以捕捉到并匹配与自己相关与否。 相关就拿走action中的要素进行逻辑处理,修改store中的状态,不相关就不对state做处理原样返回.

c. store负责存储状态并可以被react api回调,发布action

当然一般不会直接把两个库拿来用,在React和Redux之间还有一个binding叫做react-redux, 提供一个Provider和connect :

a. Provider是一个普通组件,可以作为顶层app的分发点,它只需要store属性就可以了。 它会将state分发给所有被connect的组件,不管它在哪里,被嵌套多少层

b. connect是一个科里化函数, 意思是先接受两个参数(数据绑定mapStateToProps和事件绑定mapDispatchToProps), 再接受一个参数(将要绑定的组件本身)

mapStateToProps: 构建好Redux系统的时候,它会被自动初始化,但是你的React组件并不知道它的存在,因此你需要分拣出你需要的Redux状态,所以你需要绑定一个函数,它的参数是state,简单返回你关心的几个值

mapDispatchToProps: 声明好的action作为回调,也可以被注入到组件里,就是通过这个函数,它的参数是dispatch,通过redux的辅助方法bindActionCreator绑定所有action以及参数的dispatch,就可以作为属性在组件里面作为函数简单使用了,不需要手动dispatch。这个mapDispatchToProps是可选的,如果不传这个参数redux会简单把dispatch作为属性注入给组件,可以手动当做store.dispatch使用。这也是为什么要科里化的原因。

在这里,再次理解单向数据流,就是当用户进行操作的时候,会从组件发出一个action, 这个action流到store里面,触发store对存储在store里面的状态进行改动,然后store又触发组件基于新的状态来重新渲染.

这样的话,通过这个流程,任何状态的变化都必须通过action触发,而action又必须通过dispatcher(调度)走,所以整个应用的每一次状态变化都会从同一个地方流过.

React中一直强调的一点就是 "理解你的应用的状态变化是很困难的(managing state changing over time is hard)", 通过redux, 可以让所有的状态变化都必须留下一笔记录,这样就可以利用这个来做各种debug工具,历史回滚等.

首先要明白Redux的单一状态树的概念,所谓的单一状态树, 就是指“所有的state都以一个对象树的形式存储在一个单一的store中”

比如我们有这么一个状态树 (或者你叫它状态对象)

{
text : 'Hello China'
}

这个状态树就只有一个节点text, 可以用来描述页面中某个文本的内容,比如说一个p标签

<p>Hello China</p>

当把这个状态树改变之后,比如改为如下

{
text: 'Hello New Zealand'
}

那么文本view中对应的p标签内容也会跟着改变

<p>Hello New Zealand</p>

这里就有Redux最基础也是最重要的一个概念

"页面中的所有状态or数据, 都应该用这种状态树的形式来描述; 页面上的任何变化,都应该先去改变这个状态树,然后再通过某种方式实现到页面上"

或者换句话说, 就是用单个对象去描述页面的状态,然后通过改变这个对象来操控页面

按照这个逻辑,我们来再次理解Redux中的三剑客 Action, Reducer, Store

一. Action

Action的任务是描述 "发生了什么事情"

上面的例子中我们把text从 “Hello China” 变成了 "Hello New Zealand", 那么我们就应该用一个Action对象来描述我们的行为

function changeText(){
return{ type: 'CHANGE_TEXT',
newText: 'Hello New Zeland'
}
}

这个函数会返回一个Action对象,这个Action对象里描述了"页面发生了什么", 随后这个对象会被传入到Reducer中

二. Reducer

Reducer 的任务是根据传入的Action对象去修改状态树

也就是说,根据传入的当前的state和action, 返回一个新的state

(state,action) => newState

上面的例子中,Reducer应该是这样的:

const initialState = {

     text: 'Hello China'
} function Reducer(state=initialState, action){
switch(action.type){
case 'CHANGE_TEXT':
return{
text: 'Hello New Zealand' }
default:
return state;
} }

三. Store

Store就是把Reducer和action联系到一起的对象。 Store主要是干以下几件事情:

维持应用的state

提供getState()方法来获取state

提供dispatch(action)方法来更新state

通过subscribe(listener)注册监听器

还是以上面的例子为例,会产生一个这样的Store

import {createStore} from 'redux'

//这里的Reducer就是上面第一步中的Reducer函数
let store = createStore(Reducer)

然后我们通过store的dispatch方法,dispatch上面那个action来改变store的状态

store.dispatch( changeText() );
store.getState(); // {text: 'Hello New Zealand'}

有个概念必须强调: Redux和React之间没有什么太大的关系。 Redux可以搭配React使用,也可以搭配Angular 甚至是纯JS使用。但我们发现React 和 Redux搭配使用非常普遍,这是因为React允许开发人员以State的形式来描述界面, 而Redux非常擅长控制state的变化

Redux和React结合使用,需要使用redux-react库

网上有一个很形象的例子:小明发现家里客厅的家具摆放不合理,都放在错误的位置上,弄的客厅有些乱。于是小明叫了3个朋友来帮助他一起把客厅的家具重新摆放,小明给他的3个朋友分别分配了任务。 现在我们根据这个实际生活中例子来说明Redux的三剑客 Store,Action,Reducer 和 React之间的关系

实际生活中的例子:

小明发现客厅家具摆放不合理 ---> 画出新的摆放图 ---> 小明给他3个朋友分配任务 ---> 3个朋友开始干活,搬放家具 ---> 客厅家具布局改变

我们把这个例子, 用React和Redux中的三剑客Store,Action,Reducer来表示

View(React)  = 客厅家具的摆放在视觉的效果上

Store(State) = 每个家具在客厅空间内的坐标(比如客厅沙发的位置 x:10 y:400)

Action = 小明给他3个朋友分配任务(谁应该干什么)

Reducer = 具体任务都干些什么活(把电视搬到沙发正对面然后靠墙的地方)

所以这整个过程是这样的

View ---> Action ---> Reducer ---> Store(state) ---> View

也就是说,首先Store(state)决定了View,  然后用户与View的交互会产生Action,这些Action会触发Reducer因而改变State, 然后State的改变又造成了View的变化

在文章的最后,总结一下Redux的基础也是重要的概念

1.Redux的核心是三剑客中的Store

2. Store 是一个JavaScript对象,通过Redux提供的createStore(reducers)方法创建

3. Store有两个核心方法: .getState() 和 .dispatch()

4. getState()返回一个JavaScript对象,代表Store当前的状态

5. dispatch()接受一个action作为参数, 将这个action调度分发给所有订阅了更新的reducer

6. 三剑客中的Action是一个JavaScript对象,一般包含type,payload等字段, 用于描述发生的事件及相关信息

7. Reducer是一个JavaScript函数, 函数签名(previousState,action) => newState, 即接受previousState和action两个参数,根据action中的内容对previousState进行更改,返回一个新的state

React 和 Redux理解的更多相关文章

  1. 实例讲解react+react-router+redux

    前言 总括: 本文采用react+redux+react-router+less+es6+webpack,以实现一个简易备忘录(todolist)为例尽可能全面的讲述使用react全家桶实现一个完整应 ...

  2. 【前端】react and redux教程学习实践,浅显易懂的实践学习方法。

    前言 前几天,我在博文[前端]一步一步使用webpack+react+scss脚手架重构项目 中搭建了一个react开发环境.然而在实际的开发过程中,或者是在对源码的理解中,感受到react中用的最多 ...

  3. 基于 React.js + Redux + Bootstrap 的 Ruby China 示例 (转)

    一直学 REACT + METEOR 但路由部分有点问题,参考一下:基于 React.js + Redux + Bootstrap 的 Ruby China 示例 http://react-china ...

  4. 个人关于React的一些理解

    ##React背景 React是当前前端最火的框架,它的理念思想及构建方法比AngularJS更适合做webApp. 它是由facebook团队研发并开源到社区,所以它有很强大的技术背景,而且它的架构 ...

  5. 基于react+react-router+redux+socket.io+koa开发一个聊天室

    最近练手开发了一个项目,是一个聊天室应用.项目虽不大,但是使用到了react, react-router, redux, socket.io,后端开发使用了koa,算是一个比较综合性的案例,很多概念和 ...

  6. 最新的chart 聊天功能( webpack2 + react + router + redux + scss + nodejs + express + mysql + es6/7)

    请表明转载链接: 我是一个喜欢捣腾的人,没事总喜欢学点新东西,可能现在用不到,但是不保证下一刻用不到. 我一直从事的是依赖angular.js 的web开发,但是我怎么能一直用它呢?看看最近火的一塌糊 ...

  7. 【前端,干货】react and redux教程学习实践(二)。

    前言 这篇博文接 [前端]react and redux教程学习实践,浅显易懂的实践学习方法. ,上一篇简略的做了一个redux的初级demo,今天深入的学习了一些新的.有用的,可以在生产项目中使用的 ...

  8. [React] 14 - Redux: Redux Saga

    Ref: Build Real App with React #14: Redux Saga Ref: 聊一聊 redux 异步流之 redux-saga  [入门] Ref: 从redux-thun ...

  9. [React] 15 - Redux: practice IM

    本篇属于私人笔记. client 引导部分 一.assets: 音频,图片,字体 ├── assets │ ├── audios │ ├── fonts │ └── images 二.main&quo ...

随机推荐

  1. Android 关于后台杀死App之后改变服务器状态的一些尝试

    前言: 如题,我的需求是:我需要在App在后台运行(未退出),调出最近运行记录,杀死App服务时,程序能够向服务器发送一条指令,以此达到我想要的目的. Android方面刚刚才开始玩,我一开始想的是可 ...

  2. NOIP模拟题 斐波那契数列

    题目大意 给定长度为$n$序列$A$,将它划分成尽可能少的若干部分,使得任意部分内两两之和均不为斐波那契数列中的某一项. 题解 不难发现$2\times 10^9$之内的斐波那契数不超过$50$个 先 ...

  3. LeetCode Output Contest Matches

    原题链接在这里:https://leetcode.com/problems/output-contest-matches/description/ 题目: During the NBA playoff ...

  4. hadoop完全分布式文件系统集群搭建

    一.准备工作: 1.找3台以上的主机(因为HDFS文件系统中保存的文件的blocak在datanode中至少要有3份或3份以上的备份,备份不能放于同一个机架上,更不能放于同一台主机上),我这里使用的是 ...

  5. 洛谷【P1004】方格取数

    浅谈\(DP\):https://www.cnblogs.com/AKMer/p/10437525.html 题目传送门:https://www.luogu.org/problemnew/show/P ...

  6. 14.Selenium+Python使用火狐浏览器问题解决

    一开始使用的是IE浏览器作为自动化浏览器,但是由于想学习无头模式,故选择FireFox作为浏览器,以下是遇到的相关问题: 1.简单代码 from selenium import webdriver d ...

  7. 怎么让eclipse调试的时候不进入 class文件中去

    Eclipse -> Window ->Preferences ->Java ->Debug "Suspend execution on uncaught excep ...

  8. 分治思想的应用:C++实现快速排序和随机化的快速排序

    分治思想的应用:C++实现快速排序和随机化的快速排序 原创 2014年09月08日 14:04:49 标签: 快速排序 / 随机化快速排序 / 排序算法 / 数据结构 947 1. 快速排序时冒泡排序 ...

  9. PostgreSQL 数据库角色

    数据库角色PostgreSQL使用角色的概念管理数据库访问权限.一个角色可以被看成是一个数据库用户或者是一个数据库用户组,这取决于角色被怎样设置.角色可以拥有数据库对象(例如,表和函数)并且能够把那些 ...

  10. Py修行路 Pandas 模块基本用法

    pandas 安装方法:pip3 install pandas pandas是一个强大的Python数据分析的工具包,它是基于NumPy构建的模块. pandas的主要功能: 具备对其功能的数据结构D ...