React/ReactNative 状态管理终于懂了!redux redux-toolkit 与 rematch 对比总结

有同学反馈开发 ReactNative 应用时状态管理不是很明白,这个问题我之前刚接触 React 时也遇到过,看了好多文章和视频才终于明白,不得不说,React 及三方库这方面做的有点过于复杂了!

在前面的几篇文章里我们知道了 redux redux-toolkit 和 rematch 如何使用:

  1. # React/ReactNative 状态管理: redux 如何使用
  2. # React/ReactNative 状态管理: redux-toolkit 如何使用
  3. # React/ReactNative 状态管理: rematch 如何使用

这篇文章里,我们来站在更高的角度对比总结一下。

本文主要内容:

  1. 什么是状态管理
  2. 有哪些方案,优缺点和使用场景
  3. Redux React-Redux Redux-Toolkit 和 Rematch 的区别

什么是状态管理

状态(State),就是影响 UI 布局、随着用户操作而变化的变量,比如 checkbox 的勾选状态。

状态管理,就是提供状态的这些操作:

  1. 初始化状态

    1. initState
  2. 获取状态

    1. useSelector
  3. 根据状态展示 UI

  4. 根据操作更新状态

    1. dispatch + action

Android 中如何管理状态?

  1. 根据 SP/MMKV 或者服务端数据 初始化状态

  2. 用户点击后,根据当前状态和操作,更新状态

    1. state + action = new state
  3. 状态变更后,通过 listener 或者 LiveData 通知监听者刷新

React 中提供的状态管理方式略微多一些,根据状态的使用范围,分别有这些 API:

image.png

redux 简介及案例

https://github.com/reduxjs/redux

Predictable state container for JavaScript apps

redux 官方介绍,它是一个可预测的状态容器:

  1. 可预测(可追溯) -> 将状态变更收拢到一起,方便查看变化、排查问题
  2. 状态容器:保存着全局状态 -> store

核心的三个元素:

  1. Store: 一个全局的对象(可以理解为一个 JSON )
  2. Action: 更新指令,通过 type 指定行为
  3. Reducer: 状态更新函数,参数是当前状态和 action,返回一个新 state

数据流转如下图所示:

界面展示中常常有这样的疑问:“到底是哪里把状态修改了”,比如哪里暂停了播放。

使用 redux,在界面展示异常的时候,只需要去 reducer 中特定的 action 中加日志,看是哪里调用的、参数是什么。

这样做的代价是:限定了修改、获取状态的实现方式,变得繁琐。

有人可能会说了,直接把状态保存到一个全局的 state 对象不是就可以了吗,为什么要用 redux 这么复杂!

global.state = {}

这种方式虽然看着简单,带来的结果是:状态的修改变得无法追踪,类似的逻辑要分散到具体的组件里,不利于维护。

不过在Redux 中,它其实也是维护一个全局对象,只不过提供了标准的更新规范。

上图中的 middleware,可以用作日志、调试等

核心三元素

store

Store 就是一个 JavaScript 对象,全局唯一 -> “单一数据源”

{
  selected: true
}

action

action 表示要执行的状态修改行为和参数,是一个 JavaScript 对象:

{
  type: 'ADD_TODO', text: 'xxx'
}

{
  type: 'CHANGE_TODO', text: 'yyy'
}

“type” 是固定的,后面的参数名称可自定义,一般约定为 payload

const action = {
  type: 'ADD_TODO',
  payload: 'Learn Redux'
};

reducer

reducer 是状态变化处理函数,它接收 action 并修改全局状态树(修改状态)。

const reducer = (state, action ) => newState

要求是“纯函数”:

  1. 不修改参数
  2. 相同的参数,得到结果总是相同的

每个业务有一个自己的 reducer,一个应用里会有 N 个 reducer:


function filterReducer(state = 'SHOW_ALL', action) {
  if (action.type === 'SET_VISIBILITY_FILTER') {
    return action.filter
  } else {
    return state
  }
}

function todoReducer(state = [], action) {
  switch (action.type) {
    case 'ADD_TODO':
      return state.concat([{ text: action.text, completed: false }])
    case 'TOGGLE_TODO':
      return state.map((todo, index) =>
        action.index === index
          ? { text: todo.text, completed: !todo.completed }
          : todo
      )
    default:
      return state
  }
}

//全局状态管理函数
function todoApp(state = {}, action) {
  return {
    todosState: todoReducer(state.todos, action),
    filterState: filterReducer(state.visibilityFilter, action)
  }
}

example

  1. 状态管理例子从 0 开始: redux
  2. https://github.com/reduxjs/redux-fundamentals-example-app

redux-toolkit 简介及案例

https://github.com/reduxjs/redux-toolkit

https://redux-toolkit-cn.netlify.app/introduction/quick-start

    "@reduxjs/toolkit": "^1.4.0",

redux 官方推荐通过 toolkit 使用 redux,以减少模板代码:

Redux Toolkit 的本质是提供了一些工具函数,简化纯手写 Redux 代码的冗余逻辑,其中最重要的两个工具函数是:

  1. configureStore:管理所有全局状态的函数,它的返回值是一个 Store 对象;

  2. createSlice:管理分片全局状态的函数,其返回值是一个分片对象,该对象上最重要的两个属性是:

    1. actions:创建分片 action 的函数集合

      1. action 名一般为 slice 名 + action key
    2. reducer:已经创建好的分片 reducer

核心点

redux-toolkit 是怎么简化代码的呢?

和 redux 相比,toolkit 主要在两方面减少了代码:

  1. 分发行为时不再需要 action creator

    1. 不需要单独的 xxxAction 文件
  2. 接收数据时不需要 connect

在 redux 中,每次要修改状态时,需要先通过 action creator 创建一个 action,然后分发给对应的 reducer 和 connect;而在 redux-toolkit 中,通过 createSlice 创建 slice 后,可以直接导出它的 actions,这样 UI 组件就省去了创建 action 的步骤。

example

  1. 状态管理例子从 0 开始:redux-toolkit
  2. https://github.com/reduxjs/redux-essentials-example-app/tree/tutorial-steps

rematch 简介及案例

    "@rematch/core": "^2.0.1",
    "@rematch/immer": "^2.1.3",

rematch 是第三方是基于 redux 开发,封装了一些 API,用于简化代码。

它和 redux-toolkit 非常相似,它的 model 基本上可以等同于 redux-toolkit 的 slice:

不同点在于,rematch 支持多个 store。并且

example

  1. 状态管理例子从 0 开始:rematch

react-redux

https://github.com/reduxjs/react-redux

 "react-redux": "^7.2.4",

这个库主要为 React/React Native 应用提供了 1 个组件和 2 个常用的钩子函数:

  1. Provider:Provider 是一个组件,该组件接收存储所有全局状态的 Store 对象作为参数

    1. Provider 组件底层用的是 useContext,它为整个应用的其他组件提供获取 Store 对象的能力;
  2. useSelector:从 Store 中获取某个状态,参数是个函数,返回需要的变量

    1. store.getState() 获取所有状态,不建议
  3. useDispatch:用于发送指令的钩子函数,其返回值是 dispatch 函数,而 dispatch 函数的入参是 action。

            <Provider store={store}>
              <Router nativeInfo={props} />
            </Provider>

function CounterApp() {
  //获取状态
  const counter = useSelector((state) => state.counter.value);

  const dispatch = useDispatch();

  const handlePress = () => {
    //通知修改
    dispatch(counterSlice.actions.increment(10));
  };

  return (
      <View style={styles.box}>
        <Text>{counter}</Text>
        <Text onPress={handlePress}>+10</Text>
      </View>
  );
}

总结

Redux、Redux Toolkit、React-Redux 和 Rematch 都是 React 应用程序中的状态管理库,提供集中存储和管理应用程序状态的机制。下面是它们之间的区别:

  1. Redux 是一种可预测的 JavaScript 状态容器,用于管理应用程序的状态,类似于全局存储,不依赖于 UI 库或框架。它让您能够通过单个存储管理整个应用程序的状态,并使用明确定义的规则来管理状态更新。
  2. Redux Toolkit 实际上是 Redux 应用的官方套件,它提供了一些有用的工具来帮助简化 Redux 应用程序中的常见任务,例如简化构建 store 的方式、处理异步请求、处理原生的 action 处理方案。Redux Toolkit 最大的优势在于使 Redux 应用程序的代码更加简洁、精简,更容易维护。
  3. React-Redux 提供了在使用 Redux 的 React 应用中的集成方案。它使用 react-redux 中的 Provider、connect 和 mapState 等工具来实现与 React 的协同工作。
  4. Rematch 是基于 Redux 构建的框架,提供了更轻量级且易于使用的 Redux 模板和生命周期。它的目标是能够在现代 React 生态系统中提供一种更流畅和易用的体验。

综上所述,Redux 是一种通用的状态管理库,Redux Toolkit 是Redux 应用程序的官方套件,它提供了一些有用的工具来帮助简化应用程序中的常见任务,React-Redux 提供了 Redux 应用程序的 React 集成,Rematch 则是一个基于 Redux 构建的轻量级框架,它提供了简单的解决方案来处理复杂的业务逻辑。开发人员应根据其项目的特定要求和约束来选择最适合其需求的方案。

参考资料

  1. https://time.geekbang.org/column/article/517172
  2. https://hackernoon.com/redesigning-redux-b2baee8b8a38

猜你喜欢

转载自blog.csdn.net/u011240877/article/details/129777700