Skip to main content

设计思想

Redux 是 JavaScript 状态容器,提供 可预测、可调试、集中式 的状态管理。

  • 可预测: 让你开发出 行为稳定可预测、可运行在不同环境 (客户端、服务端和原生程序)、且 易于测试 的应用。

  • 集中管理: 集中管理应用的状态和逻辑可以让你开发出强大的功能,如 撤销/重做、 状态持久化 等等

  • 可调试: Redux DevTools 让你 轻松追踪 到 应用的状态在何时、何处以及如何改变。Redux 的架构会记下每一次改变,借助于 "时间旅行调试",你甚至可以把完整的错误报告发送给服务器。

  • 灵活: Redux 可与任何 UI 层框架搭配使用,它体小精干(只有 2kB,包括依赖),并且有 庞大的插件生态 来实现你的需求。

react-redux

Redux 是一个单一的状态机,它只关注 state 的变化,至于视图层怎么变化,关键在于 React-redux。

React-redux 实现了结合发布订阅模式的订阅

react-redux 提供了 Provider 组件,接收一个 store 对象(redux 的 store 对象

关键流程:初始化

利用 useSelector 传入的 selector 函数获取 Redux 中 store 对应的值 定义一个 latestSelectedState,用于保存上一次 selector 返回的值 定义 state 变化的处理函数 checkForUpdates 利用 store.subscribe 订阅一次 redux 的 store,当下次 store 变化后,触发订阅函数执行 checkForUpdates

关键流程:更新

当用户 dispacth 触发了 store 变化后,订阅函数执行 checkForUpdates 通过 store.getState()获取最新的 state 值,通过 equalityFn 函数比较 newSelectedState 和 latestSelectedState,如果有变化就执行 forceRender,触发 react 创建 update 对象,强制渲染;否则直接 return

强制渲染 关键方法: const [, forceRender] = useReducer(s => s + 1, 0) 利用 useReducer 定义了一个计数器,用于强制渲染此组件

checkForUpdates:store 变化后订阅函数触发的处理逻辑

react-redux 状态变更原理

https://juejin.cn/post/6945808822308962317

基本的数据流概念和原则

(1) 单一数据

整个应用的 全局 state 被储存在一棵对象树(object tree)中,并且这个对象树只存在于唯一 Store(存储) 中 单一数据源使得同构应用开发变得容易,将状态在统一的 对象树 中维护管理也会更加容易!

(2) 单向数据流(one-way data flow)

  1. 用 state 来描述应用程序在特定时间点的状况
  2. 基于 state 来渲染出 View
  3. 当发生某些事情时(例如用户单击按钮),state 会根据发生的事情进行更新,生成新的 state
  4. 基于新的 state 重新渲染 View

(3) 不可变性(Immutability)

对于状态(state)的描述一般都是一个大的 JavaScript 对象(Object Tree),例如

const state = {
isLoading: true,
userInfo: {
uid: 1,
wechat: 'DYBOY2020',
phone: 177****7777,
history: [1,2,3,4,5]
}
}

由于 JS 的动态性,使得对象是可以修改的,Redux 想要记录每一个状态,如果直接修改 state 中的引用类型属性,势必会导致 state 的变化不可追溯和预测。 因此 state 是只读的!唯一改变 state 的方法就是触发 action,action 是一个用于描述已发生事件的普通对象。 Redux 期望所有状态更新都是使用不可变的方式,因此,每一次的 state 变更,不会修改原对象,而是修改前一个状态(state)的克隆对象,以此来保证不可变性和正确性,同时记录每一次变化的 state。

(4) 纯函数更新 state

reducer 是一个纯函数(实现回溯),收到 store 传来的 previousState 和 action 返回 newState 更新 store 纯函数: 相同的输入,总是会得到相同的输出,并且在执行过程中没有任何副作用的函数。 为了保证数据的改变正确性,以及满足 state 不可变性的要求,因此引入了 纯函数 作为更新状态的唯一方式。

同步数据流和异步数据流

异步数据流需要 API 利用中间件调用 dispatch 来触发 action 到 reducer 中

reducer 操作 state 进行更新

同步数据流能直接调用 dispatch

实现一个简单的 redux

export default class CreateStore {
constructor(reducer, initialState){
this.currentReducer = reducer
this.currentState = initialState
this.listeners = []
this.isDispatching = false
}

getState() {
return this.currentState
}
subscribe(listener) {
this.listeners.push(listener)
return function unsubscribe(){
let index = this.listeners.indexOf(listener)
this.listeners.splice(index,1)
}
}
dispatch(action){
try {
this.isDispatching = true
this.currentState = currentReducer(currentState, action)
} finally {
this.isDispatching = false
}

this.listener.slice().forEach(listener => listener())
return action
}

}