多译 · 更新日志页面开发(二):初识Redux

最近课程压力不算特别重,多花一些时间去做miniproject。

前几天看完《React16.4 开发简书项目 从零基础入门到实践》系列中的React基础部分,感悟颇深。React的这种设计理念,让我觉得写web是一件十分优雅的事情。这种数据驱动的理念让曾经一些复杂交互的实现变得十分简单。

然鹅React虽然很优雅,但是不够强大。

之前的实践中,我们的应用逻辑很简单,可能只有一个页面和两三个组件。但是尽管如此,在本系列的上一篇文章 初识 React 中的最后一节中,子组件向父组件传递数据已经是一件比较复杂的事情了。

设想倘若一个项目中有10个页面和数十个组件,这些组件批次之间必然会互相使用并且修改一些相同的数据。这个时候我们的React对于这些数据的传递就会十分复杂,从而让我们抓狂。

幸运的是我们有Redux

1、为什么要有Redux

如果你不知道是否需要Redux, 那就是不需要它

只有遇到React实在解决不了的问题,你才需要Redux

这两句话也是对我们上面进行的场景思考的印证。

反过来想,Redux解决的就是比较复杂的情形

阮一峰的博客中有给出具体的例子

如果UI层非常简单,没有很多互动,Redux 就是不必要的,用了反而增加复杂性。比如:

  • 用户的使用方式非常简单
  • 用户之间没有协作
  • 不需要与服务器大量交互,也没有使用 WebSocket
  • 视图层(View)只从单一来源获取数据

而如下情况则需要使用 Redux:多交互、多数据源。

  • 用户的使用方式复杂
  • 不同身份的用户有不同的使用方式(比如普通用户和管理员)
  • 多个用户之间可以协作
  • 与服务器大量交互,或者使用了WebSocket
  • View要从多个来源获取数据

从组件角度看,如果有以下场景,可以考虑使用 Redux。

  • 某个组件的状态,需要共享
  • 某个状态需要在任何地方都可以拿到
  • 一个组件需要改变全局状态
  • 一个组件需要改变另一个组件的状态

2、设计思想

Redux 的设计思想就是进行状态管理

  1. Web 应用是一个状态机,状态与视图一一对应
  2. 所有的状态都保存在一个对象里面

3、Redux的工作流程

Redux Flow

Store

Store保存了所有的state

整个应用只能有一个Store

Redux 提供了 createStore 方法,接收另一个函数生成store对象

Action

State和View是一一对应的,View可以很容易的获取State,但是View如何操控State呢,这时候就需要Action的定义

action表示 View 发出的通知,通知 Store来改变State

action是一个对象,type属性是必须的,一个action的规范

1
2
3
4
const action = {
type: 'save',
payload:{/*some data*/}
}

一个好的习惯是 将type的字符串以同名变量保存,这样有助于维护与debug,以免因为输入错误而导致action失效。要知道这种输入错误往往是很难找到的。
例如

1
2
3
4
5
6
7
8

const ACTION = {
SAVE: 'save'
}
const action = {
type: ACTION.SAVE,
payload:{/*some data*/}
}

如果Action很多的话可以定义一个函数来生成Action,这个函数就是 Action Creator

store.dispatch() 是View发出Action的唯一方式,它接收一个action并且发送

Reducer

Store 收到 Action 以后,必须给出一个新的 State,这样 View 才会发生变化。这种 State 的计算过程就叫做 Reducer。

Reducer 是一个函数,它接受 Action 和当前 State 作为参数,返回一个新的 State。

1
2
3
4
5
6
7
8
const reducer = (state = defaultState, action) => {
switch (action.type) {
case 'ADD':
return state + action.payload;
default:
return state;
}
};

store.dispatch方法会触发 Reducer 的自动执行。为此,Store 需要知道 Reducer 函数,做法就是在生成 Store 的时候,将 Reducer 传入createStore方法

这个reducer的命名很容易让我们联想到reduce方法,其实仔细思考一下这是有道理的。reducer本质上也是对 preState 和 data 生成一个nextState

纯函数

Reducer 函数最重要的特征是,它是一个纯函数。也就是说,只要是同样的输入,必定得到同样的输出。

纯函数是函数式编程的概念,必须遵守以下一些约束。

  • 不得改写参数
  • 不能调用系统 I/O 的API
  • 不能调用Date.now()或者Math.random()等不纯的方法,因为每次会得到不一样的结果

这和我们之前的文章中,不允许直接改变state中的list,而是要拷贝一份list然后返回新的数组给state 是一致的

4、个人感悟

经过最近为时一周的React+Redux学习经历,我对于React的理念有了基本的概念。

React的本质就是对于组件的组织与维护,其组织体现在通过布局等方式将这些组件排列,展现在用户面前。而维护的本质则在于组件的状态管理,不论是组件内部的状态管理还是通过Redux对于状态进行管理。

我们通过状态管理来操控页面的变化。

参考资料: Redux 入门教程(一):基本用法 作者: 阮一峰