CAUTION

新项目不再推荐使用 Reduck,可以使用社区中的状态管理工具,例如 Jotaizustandvaltio 等。

快速上手

Reduck 是 Modern.js 团队开发的遵循 MVC 模式的状态管理库,底层状态存储基于 Redux 实现,同时提供更高层级的抽象,并完全兼容 Redux 生态。

Reduck 的目标是以 MVC 模式组织 React 应用开发结构,将业务逻辑维护在 Model 层,业务逻辑与 UI 解耦,让开发业务逻辑更集中、更简单,同时通过更高层级的抽象,减少重复工作(样板代码)。

Reduck 在 MVC 模式中,扮演 M(Model) 的角色,React UI Component 对应 V(View),从 Reduck 中获取 Model 并修改 Model 的 React Container Component 对应 C(View Controller/Container)。

Modern.js 的状态管理解决方案,是通过内置 Reduck 实现的。在 Modern.js 中使用 Reduck,不仅免去了手动集成的环节,而且所有 Reduck API 都可以从 Modern.js 的 Runtime 包中直接导入使用,具有更好的一致性体验。

INFO
  1. Modern.js 中使用 Reduck API,需要先设置 runtime.state 以启用状态管理插件。
  2. Reduck 也可以脱离 Modern.js 作为状态管理库单独使用

核心概念

Reduck 中的核心概念只有 4 个: Model、State、Actions、Effects。

Model: 对独立模块的逻辑和所需状态的封装,由 State、Actions、Effects 组成。

State: Model 中保存的状态。

Actions: 用于修改 State 的纯函数,函数必须是同步的。

Effects: 用于修改 State 的带有副作用的函数,函数可以是异步的。Effects 中可以调用自身或其他 Model 的 Actions 和 Effects。

Reduck 数据流如下图所示:

Reduck 数据流

基本用法

下来我们以一个简单的 计数器 应用为例,演示 Reduck 的基本用法。

首先,我们定义一个名为 count 的 Model:

import { model } from '@modern-js/runtime/model';

const countModel = model('count').define({
  state: {
    value: 1,
  },
});

export default countModel;

我们使用 API model 创建 countModelcountModel 当前只包含存储计数器值的状态,即代码中的 value

我们定义一个 action,用于计算器自增加 1:

import { model } from '@modern-js/runtime/model';

const countModel = model('count').define({
  state: {
    value: 1,
  },
  actions: {
    add(state) {
      state.value += 1;
    },
  },
});

export default countModel;

add action 中,我们可以直接修改 state 的值,进行加 1 操作,而不需要把 state 作为不可变对象进行操作,这是因为 Reduck 集成了 immer,可以直接修改原 state 对象。

接下来,我们演示如何在组件中使用 Model。

新建一个组件 Counter,在组件内通过 useModel API 使用 countModel

import { useModel } from '@modern-js/runtime/model';
import countModel from './models/count';

function Counter() {
  const [state, actions] = useModel(countModel);

  return (
    <div>
      <div>counter: {state.value}</div>
      <button onClick={() => actions.add()}>add</button>
    </div>
  );
}

useModel 获取 countModelstateactions,组件展示当前计算器的值,点击 add 按钮,计数器自增 1。

INFO

由于使用的案例比较简单,这里并没有严格按照 MVC 模式进行分层,组件 Counter 同时起到了 V 和 C 两层的作用。

最终演示效果如下:

countModel

这样,我们就完了一个简单的计数器应用。本节完整的示例代码可以在这里查看。