Redux的三个基本概念

Redux的三个基本概念

Content #

Redux 引入的概念其实并不多,主要就是三个:State、Action 和 Reducer。

  1. 其中 State 即 Store,一般就是一个纯 JavaScript Object。
  2. Action 也是一个 Object,用于描述发生的动作。
  3. 而 Reducer 则是一个函数,接收 Action 和 State 并作为参数,通过计算得到新的 Store。

它们三者之间的关系可以用下图来表示:

在 Redux 中,所有对于 Store 的修改都必须通过这样一个公式去完成,即通过 Reducer 完成,而不是直接修改 Store。这样的话,一方面可以保证数据的不可变性(Immutable),同时也能带来两个非常大的好处。

  1. 可预测性(Predictable):即给定一个初始状态和一系列的 Action,一定能得到一致的结果,同时这也让代码更容易测试。
  2. 易于调试:可以跟踪 Store 中数据的变化,甚至暂停和回放。因为每次 Action 产生的变化都会产生新的对象,而我们可以缓存这些对象用于调试。 Redux 的基于浏览器插件的开发工具就是基于这个机制,非常有利于调试。

比如说要实现“加一”和“减一”这两个功能,对于 Redux 来说,我们需要如下代码:

import { createStore } from 'redux'

// 定义 Store 的初始值
const initialState = { value: 0 }

// Reducer,处理 Action 返回新的 State
function counterReducer(state = initialState, action) {
  switch (action.type) {
    case 'counter/incremented':
      return { value: state.value + 1 }
    case 'counter/decremented':
      return { value: state.value - 1 }
    default:
      return state
  }
}

// 利用 Redux API 创建一个 Store,参数就是 Reducer
const store = createStore(counterReducer)

// Store 提供了 subscribe 用于监听数据变化
store.subscribe(() => console.log(store.getState()))

// 计数器加 1,用 Store 的 dispatch 方法分发一个 Action,由 Reducer 处理
const incrementAction = { type: 'counter/incremented' };
store.dispatch(incrementAction);
// 监听函数输出:{value: 1}

// 计数器减 1
const decrementAction = { type: 'counter/decremented' };
store.dispatch(decrementAction)
// 监听函数输出:{value: 0}

通过这段代码,我们就用三个步骤完成了一个完整的 Redux 的逻辑:

  1. 先创建 Store;
  2. 再利用 Action 和 Reducer 修改 Store;
  3. 最后利用 subscribe 监听 Store 的变化。

需要注意的是,在 Reducer 中,我们每次都必须返回一个新的对象,确保不可变数据(Immutable)的原则。一般来说,我们可以用延展操作符(Spread Operator)来简单地实现不可变数据的操作,例如:

return {
  ...state, // 复制原有的数据结构
  value: state.value + 1, // 变化 value 值使其 + 1
}

这在大多数场景下已经足够使用。当然对于复杂的数据结构,也有一些第三方的库可以帮助操作不可变数据,比如 Immutable、Immer 等等。

通过这个例子,我们看到了纯 Redux 使用的场景,从而更加清楚地看到了 Store、Action 和 Reducer 这三个基本概念,也就能理解 State + Action => New State 这样一个简单却核心的机制。

Viewpoints #

From #

07|全局状态管理:如何在函数组件中使用 Redux?