有同学反馈开发 ReactNative 应用时状态管理不是很明白,这个问题我之前刚接触 React 时也遇到过,看了好多文章和视频才终于明白,不得不说,React 及三方库这方面做的有点过于复杂了!
在前面的几篇文章里我们知道了 redux redux-toolkit 和 rematch 如何使用:
这篇文章里,我们来站在更高的角度对比总结一下。
本文主要内容:
状态(State),就是影响 UI 布局、随着用户操作而变化的变量,比如 checkbox 的勾选状态。
状态管理,就是提供状态的这些操作:
Android 中如何管理状态?
React 中提供的状态管理方式略微多一些,根据状态的使用范围,分别有这些 API:
https://github.com/reduxjs/redux
Predictable state container for JavaScript apps
redux 官方介绍,它是一个可预测的状态容器:
核心的三个元素:
数据流转如下图所示:
界面展示中常常有这样的疑问:“到底是哪里把状态修改了”,比如哪里暂停了播放。
使用 redux,在界面展示异常的时候,只需要去 reducer 中特定的 action 中加日志,看是哪里调用的、参数是什么。
这样做的代价是:限定了修改、获取状态的实现方式,变得繁琐。
有人可能会说了,直接把状态保存到一个全局的 state 对象不是就可以了吗,为什么要用 redux 这么复杂!
global.state = {}
这种方式虽然看着简单,带来的结果是:状态的修改变得无法追踪,类似的逻辑要分散到具体的组件里,不利于维护。
不过在Redux 中,它其实也是维护一个全局对象,只不过提供了标准的更新规范。
上图中的 middleware,可以用作日志、调试等
Store 就是一个 JavaScript 对象,全局唯一 -> “单一数据源”
{
selected: true
}
action 表示要执行的状态修改行为和参数,是一个 JavaScript 对象:
{
type: 'ADD_TODO', text: 'xxx'
}
{
type: 'CHANGE_TODO', text: 'yyy'
}
“type” 是固定的,后面的参数名称可自定义,一般约定为 payload
const action = {
type: 'ADD_TODO',
payload: 'Learn Redux'
};
reducer 是状态变化处理函数,它接收 action 并修改全局状态树(修改状态)。
const reducer = (state, action ) => newState
要求是“纯函数”:
每个业务有一个自己的 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)
}
}
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 代码的冗余逻辑,其中最重要的两个工具函数是:
redux-toolkit 是怎么简化代码的呢?
和 redux 相比,toolkit 主要在两方面减少了代码:
在 redux 中,每次要修改状态时,需要先通过 action creator 创建一个 action,然后分发给对应的 reducer 和 connect;而在 redux-toolkit 中,通过 createSlice 创建 slice 后,可以直接导出它的 actions,这样 UI 组件就省去了创建 action 的步骤。
"@rematch/core": "^2.0.1",
"@rematch/immer": "^2.1.3",
rematch 是第三方是基于 redux 开发,封装了一些 API,用于简化代码。
它和 redux-toolkit 非常相似,它的 model 基本上可以等同于 redux-toolkit 的 slice:
不同点在于,rematch 支持多个 store。并且
https://github.com/reduxjs/react-redux
"react-redux": "^7.2.4",
这个库主要为 React/React Native 应用提供了 1 个组件和 2 个常用的钩子函数:
<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 应用程序中的状态管理库,提供集中存储和管理应用程序状态的机制。下面是它们之间的区别:
综上所述,Redux 是一种通用的状态管理库,Redux Toolkit 是Redux 应用程序的官方套件,它提供了一些有用的工具来帮助简化应用程序中的常见任务,React-Redux 提供了 Redux 应用程序的 React 集成,Rematch 则是一个基于 Redux 构建的轻量级框架,它提供了简单的解决方案来处理复杂的业务逻辑。开发人员应根据其项目的特定要求和约束来选择最适合其需求的方案。