有同学反馈开发 ReactNative 应用时状态管理不是很明白,接下来几篇文章我们来对比下 React 及 ReactNative 状态管理常用的几种框架的使用和优缺点。

上一篇文章介绍了 redux 的升级版 redux-toolkit 的使用,这篇文章我们来看下社区里比较出名的 redux 的升级库:rematch。

下面是使用 React 和 rematch 创建一个简单的 Todo List App 的代码示例,完整代码见文章末尾:

  1. 首先,在命令行中输入以下命令新建一个 React 应用:
npx create-react-app todolist
  1. 安装 rematch 和 react-redux:
npm install @rematch/core react-redux
  1. 创建一个 models.ts 文件,在其中继承 rematch 的 Models,定义当前业务的所有 model 类型
import { Models } from "@rematch/core";//导出当前业务的所有 model 的类型
export interface RootModel extends Models<RootModel> {//暂时先空着
}//创建并导出所有 model 的实例
export const models: RootModel = {}

在上面的代码中,RootModel 是当前业务的所有 model 接口。

rematch 中的 model 和 redux-toolkit 的 slice 概念类似,都表示一个业务的初始状态和支持的操作。

  1. 创建一个 todo.ts 文件,在其中使用 rematch 的 createModel 创建一个 todo 的业务 model:
import { createModel } from "@rematch/core";
import { State, TODO } from "../../module/todo";
import { RootModel } from "./models";const initState : State = {todos: [{text: "zsx clean room, model init data"}]
};//创建一个 model(类似 redux-toolkit 的 slice),包括一个业务的初始状态、状态处理和变更后的影响
//最核心的地方 **
export const todo = createModel<RootModel> () ({name: 'todo',state: initState,//reducers 需要是纯函数:只依赖参数进行计算,不使用外部数据reducers: {//与 toolkit 的 slice 不同,参数直接是 payload,更简单addTodo: (state: State, payload: string) => {//返回新状态return {...state,todos: [...state.todos, {text: payload}]};},deleteTodo: (state: State, payload: string) => {const todos = state.todos.filter((item: TODO, index: number)=> {return item.text !== payload});return {...state,todos}}},
})

从上面的代码中我们可以看到,rematch 中的 model 和 redux-toolkit 的 slice 概念类似,在其中可以指定名称、初始状态 和 reducers。

不同之处:

  1. rematch 的 reducer,参数是 payload,而不是 action,更加直接
  2. rematch 的 reducer,必须有返回值,否则会报错!
  3. rematch 直接导出 createModel 的返回值,不需要分别导出 actions 和 reducer

再次强调一下,rematch 中使用 model 表示某个业务的状态管理,我们刚才通过 createModel 创建的 todo 是一个 model,表示 todo 业务的状态管理。

  1. 回到第三步创建的 models.ts 文件,把我们刚才创建的 todo 添加到 RootModel 的成员里:
import { Models } from "@rematch/core";
import {todo} from "./todo";//导出当前业务的所有 model 的类型
export interface RootModel extends Models<RootModel> {//这里的名称就是后续调用 dispatch 的名称todo: typeof todo
}//创建并导出所有 model 的实例
export const models: RootModel = {todo: todo}

通过上面的代码,就可以知道,当前所有业务 model 里,有一个叫做“todo” 的 model。

同时,导出的所有 model 的实例 models,也有一个成员 todo,它就是前面通过 createModel 创建的 todo model。

  1. 使用 rematch 的 init 函数创建 store:
import { init, RematchDispatch, RematchRootState } from "@rematch/core";
import { models, RootModel } from "./model/models";//创建 store,参数就是所有业务的 model
export const store = init({models
})store.subscribe( () => {console.log('store update >>> ' + JSON.stringify(store.getState()))
})store.dispatch.todo.addTodo("add from store")//导出类型,用于业务组件里使用
export type Store = typeof store
export type Dispatch = RematchDispatch<RootModel>
export type RootState = RematchRootState<RootModel>

从上面的代码可以看到,init 函数的参数就是我们上一步导出的所有业务 model 的对象 models。

init 返回的 store 本质上就是 redux 的 store,因此和 redux store 一样,也支持 subscribe 和 dispatch。

创建完 store 以后,我们还需要导出几个类型:Store Dispatch 和 RootState,他们用于在 typescript UI 组件里获取状态或者分发行为。

7.和其他库一样,通过 react-redux 的 Provider 将 store 提供给组件树:

import RematchTodoApp from './rematch/RematchTodoApp';
import { store } from './rematch/store';const root = ReactDOM.createRoot(document.getElementById('root') as HTMLElement
);//分发给子元素
root.render(<Provider store={store}><RematchTodoApp/></Provider>
);

RematchTodoApp 是下一步要创建的 UI 组件

8.创建 UI 组件,在其中使用 react-redux 的 useSelector 和 useDispatch 获取状态和分发行为:

import {useState} from "react";
import { useDispatch, useSelector } from "react-redux";
import { TODO } from "../module/todo";
import { Dispatch, RootState } from "./store";//业务通过 useSelector 获取数据;通过 useDispatch 分发
const RematchTodoApp = () => {//和 toolkit 类似,需要根据 model 名称访问数据//参数类型就是 store 里导出的类型const todos = useSelector((state: RootState) => {return state.todo.todos;});//和 toolkit 不同的在于,需要声明类型//同时分发的时候也有些不同const dispatch = useDispatch<Dispatch>();const [text, setText] = useState('');const handleInput = (e: any) => {setText(e.target.value)}const handleAddTodo = () => {// 分发的时候,通过 dispatch.<model name>.<reducer name> 的方式调用,参数就是 payload 的类型//toolkit 里的写法:dispatch(addTodo(text))dispatch.todo.addTodo(text)setText('')}const handleDeleteTodo = (text: string) => {//toolkit 里的写法:dispatch(deleteTodo(text))dispatch.todo.deleteTodo(text)}return (<div style={{display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center'}}><h1>This Is Rematch TODO App.</h1><ul>{todos && todos.map((todo: TODO, index: any) => {return (<li key={index}><span>{todo.text}</span><button style={{marginLeft: '12px'}} onClick={() => handleDeleteTodo(todo.text)}>finish</button></li>)})}</ul><div style={{display: 'flex', flexDirection: 'row'}}><input value={text} onChange={handleInput}/><button style={{marginLeft: '12px'}} onClick={handleAddTodo}>Add Todo</button></div></div>)
}export default RematchTodoApp;

在上面的代码中,我们使用 useSelector 获取当前业务需要的状态,因为拿到的是所有业务的数据,因此需要通过 todo 的业务名称获取到属于 todo 的数据:

    //和 toolkit 类似,需要根据 model 名称访问数据//参数类型就是 store 里导出的类型 RootStateconst todos = useSelector((state: RootState) => {return state.todo.todos;});

需要注意的是,state.todo.todos 里的「todo」是我们第五步在 models 里增加 todo model 时 key 的名称。

随后我们使用 useDispatch 获取 dispatch,和 toolkit 不同的在于,需要声明类型:

    const dispatch = useDispatch<Dispatch>();const handleAddTodo = () => {// 分发的时候,通过 dispatch.<model name>.<reducer name> 的方式调用,参数就是 payload 的类型//toolkit 里的写法:dispatch(addTodo(text))dispatch.todo.addTodo(text)setText('')}

在分发行为的时候,toolkit 是这样:dispatch(addTodo(text)),rematch 是这样:dispatch.todo.addTodo(text) ,个人感觉 rematch 这种略微好一点,避免了层层嵌套。

总结一下,通过 rematch 管理状态分这几步:

  1. 继承 rematch 的 Models,定义当前业务的所有 model 类型

  2. 使用 rematch 的 createModel 创建一个 todo 的业务 model,声明初始化状态、reducers

    1. 每个 reducer 的参数是 state 和 payload,必须有返回值
  3. 使用 rematch 的 init 函数创建 store,参数就是所有 model

    1. 导出 RematchDispatch RematchRootState 和 store 的类型
  4. 通过 Provider 分发给组件树

  5. 在 UI 组件中使用 react-redux 的 useSelector 和 useDispatch 获取状态和分发行为

可以看到,rematch 和 redux-toolkit 有很大的相似度。

完整代码:https://github.com/shixinzhang/redux-sample/tree/main/src/rematch

React/ReactNative 状态管理: rematch 如何使用相关推荐

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

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

  2. 【视频】React ReduxToolkit状态管理:创建store对象及redux调试工具的安装方法

    React ReduxToolkit状态管理:创建store

  3. react全局状态管理_rxv: 在React中用Vue3的reactivity包实现状态管理。

    前言 React的状态管理是一个缤纷繁杂的大世界,光我知道的就不下数十种,其中有最出名immutable阵营的redux,有mutable阵营的mobx,react-easy-state,在hooks ...

  4. Recoil 是 React 的状态管理库

    Recoil 是 React 的状态管理库,因此你需要将 Recoil 安装到 React 项目中才能使用.创建 React 项目最方便且推荐的方式是使用 Create React App: npx ...

  5. react全局状态管理_react 状态管理的复杂度来源

    Ui = f(data) 本来按照这个公式,前端开发应该是非常愉悦的.最近发现有一些复杂度是因为现有的工具造成的,导致上面这个公式并不成立. 如果 data 不是一个浏览器的数据,而是数据库里的数据. ...

  6. react usecontext_Vue3原理实战运用,我用40行代码把他装进了React做状态管理

    前言 vue-next是Vue3的源码仓库,Vue3采用lerna做package的划分,而响应式能力@vue/reactivity被划分到了单独的一个package中. 如果我们想把它集成到Reac ...

  7. hooks组件封装 react_名符其实的react下一代状态管理器hox

    自从 React16 版本发布 Hooks 以来,大家纷纷上车尝鲜.毫无疑问, Hooks 在一定程度上解决了组件间功能和逻辑复用的问题,在组件间的逻辑的封装和复用确实真香,但 Hooks 在数据状态 ...

  8. 名符其实的react下一代状态管理器hox

    前言 自从React16版本发布Hooks以来,大家纷纷上车尝鲜.毫无疑问,Hooks在一定程度上解决了组件间功能和逻辑复用的问题,在组件间的逻辑的封装和复用确实真香,但Hooks在数据状态的共享方法 ...

  9. React 全局状态管理的 3 种底层机制

    现代前端框架都是基于组件的方式来开发页面.按照逻辑关系把页面划分为不同的组件,分别开发不同的组件,然后把它们一层层组装起来,把根组件传入 ReactDOM.render 或者 vue 的 $mount ...

最新文章

  1. 验证插件——jquery.validate.js
  2. ubuntu linux的特点,16个新特性,让你爱上Ubuntu 20.04,
  3. torch的拼接函数_从零开始深度学习Pytorch笔记(13)—— torch.optim
  4. java实现九九乘法表的输出
  5. linux 监控网络IO、磁盘、CPU、内存
  6. redis-full-check
  7. matlab lyap,Matlab的Lyapunov、Sylvester和Riccati方程的Matlab求解
  8. 计算机技术在档案管理中的应用,浅谈计算机技术在档案管理中的应用
  9. 不好的测试实践——软件测试的尽早介入
  10. 3说明书_BMW新3系说明书上没写的6条信息
  11. java 循环字符_在Java中从循环结果创建字符串
  12. Hiho----无间道之并查集
  13. autoware中pure_pursuit控制和MPC控制解析
  14. 汇编语言 数据寄存器AX、BX、CX、DX
  15. 常用的字符串方法大全
  16. OpenCV—播放AVI视频
  17. 【测试】功能测试用例设计方法总结
  18. 科学上网后(关掉VPN)之后无法正常连接网络
  19. 头条小程序 button组件 设置边框问题
  20. vscode中编写代码时tab键不能用

热门文章

  1. 安卓锁屏灭屏加载流程
  2. 苹果账号被禁用怎么办?
  3. C++中的动态空间扩充方法
  4. Windows域控管理—如何使用powershell远程连接服务器
  5. Android自动换行布局
  6. ossutil覆盖_查看选项_命令行工具ossutil_常用工具_对象存储 OSS - 阿里云
  7. AWS入门指南之一:怎样创建免费的AWS账号
  8. 程序员的江湖 务必掌握这些黑话!
  9. 合并多个excel的行到一个excel
  10. 索尼录音笔怎么导出录音内容_追黄宗泽新剧追到了索尼录音笔?没办法,就是便携好用颜值高...