初探 Redux(1)| 青训营笔记

114 阅读4分钟

这是我参与「第四届青训营 」笔记创作活动的的第6天。在青训营的低代码项目开发中,编辑组件间状态的混乱,随着代码的不断堆砌,对开发进展的影响变得越来越严重。之前因为使用的主要是 Vue 框架,对于状态管理的意识较为淡薄,也借此机会学习了解一下 React 中状态管理工具 Redux 的基础知识与代码实践。

什么是 Redux

Redux 是一个使用叫做“action”的事件来管理和更新应用状态的模式和工具库 它以集中式Store(centralized store)的方式对整个应用中使用的状态进行集中管理,其规则确保状态只能以可预测的方式更新。—— Redux 基本思想

Redux 提供的工具可以帮助开发者在前端项目中管理“全局”状态。

使用这样的管理工具(以声明式的方式)可以让开发者更容易理解程序状态在何时何地、为什么更新以及如何更新,有利于提升开发者对程序状态的控制能力。

什么时候使用 Redux

Redux 不是必要的(可以不用),但有的时候又是必要的(不得不用,用了就爽)。作为一款状态管理工具,其工具属性表明它可以被一些通用工具(React 组件中的状态管理)所替代,但确实解决了开发中一些情况下的痛点。而什么时候在项目中使用它,就是开发者应当去学习、思考的问题了。(在后续的部分也阐明了部分对此问题的思考)

适用情况:

  • 在应用的大量地方,都存在大量的状态
  • 应用状态会随着时间的推移而频繁更新
  • 更新该状态的逻辑可能很复杂
  • 中型和大型代码量的应用,很多人协同开发

Redux 术语与概念

建议在了解 Redux 整体后反复阅读理解

state 管理

state -> view -> action -> state 是组件中常见的数据流向。

  • state:驱动应用的真实数据源头
  • view:基于当前状态的 UI 声明性描述
  • actions:根据用户输入在应用程序中发生的事件,并触发状态更新

多个组件需要共享和使用相同state时,“提升 state”的方法并不总是有效的。Redux 共享 state 可以解决此问题。

不可变性 Immutability

JS 中的对象是可变的(mutable),修改对象中的内容,不会导致 obj 的引用变化,而 obj 对象确实发生了改变。

const obj = { a: 1, b: 2 }\
// obj 仍然还是那个对象,但它的内容已经变了,数组同理
obj.b = 3

使用不可变的方式更新对象,必须复制原来的对象,更新复制体。(在 React 中使用可变方式的更新(上面代码块的方式)大多不会触发页面的重新渲染 —— React 认为当前的 state 还是原来的 state。)

const obj = {
  a: {
    // 为了安全的更新 obj.a.c,需要先复制一份
    c: 3
  },
  b: 2
}

const obj2 = {
  // obj 的备份
  ...obj,
  // 覆盖 a
  a: {
    // obj.a 的备份
    ...obj.a,
    // 覆盖 c
    c: 42
  }
}

Redux 组成

  • State 状态

    • DomainData:服务端数据
    • UI State:决定当前 UI 的状态
    • App State:APP级别的状态
  • Action 事件

    数据从应用传递到 store 的载体,是 store 数据唯一的来源

    • 本质上是一个 JS obj
    • 内部有 type 属性表示执行的动作,多数情况下是字符串常量
    • 多数为纯函数,描述一个执行的过程(声明式),不直接更新 State
  • Reducer

    本质是一个函数,用于响应发送过来的 action 数据,把 state 发送给 Store

    • 仅使用 state 和 action 参数计算新的状态值
    • 禁止直接修改 state。必须通过复制现有的 state 并对复制的值进行更改的方式来做 不可变更新(immutable updates)
    • 禁止任何异步逻辑、依赖随机值或导致其他“副作用”的代码
  • Store

    把 action 和 reducer 联系到一起的对象

    • 维持应用的 state,createStore() 构建 store
    • 关联 action 和 reducer
    • 提供 getState() 获取 State
    • 提供 dispatch() 发送 action
    • 提供 subscribe() 注册监听,返回值注销监听。响应 reducer 返回值

Redux 实践

  • Redux store 是使用 Redux Toolkit 中的 configureStore 函数创建
  • Redux 切片(Slice)是应用中单个功能的 Redux reducer 逻辑和 action 的集合,通常一起定义在一个文件中

来自 Redux 官网的 counter 样例: redux-essentials-counter-example - CodeSandbox

  • createSlice 内部使用了一个名为 Immer 的库。 Immer 使用一种称为 “Proxy” 的特殊 JS 工具来包装您提供的数据。使开发者在其中可以使用 mutate 的方式更新值。

    上述改变的内容为 state 中的内容(对象的参数),state (直接索引值)依然是不可直接改变的,否则会导致一系列问题。

  • thunk 是一种特定类型的 Redux 函数,可以包含 异步逻辑,Redux Toolkit 的 configureStore 函数能够自动配置 thunk,所以可以直接使用异步函数编写 reducer。

hooks

解决了在组件中无法访问到 store 的问题。

  • useSelector 提取数据

  • useDispatch dispatch action

参考资料