Skip to content

React 状态管理解决方案

安装

sh
pnpm install @yl_lowcode/reactive
sh
npm install @yl_lowcode/reactive

reactive 响应式状态管理

基于 useSyncExternalStore 封装的轻量响应式状态管理方案,无需 Context,天然支持 SSR,具备自动依赖追踪深层嵌套响应能力。

基础用法

调用 reactive(initialState) 创建一个 store,在组件内通过 store.useSnapshot() 订阅状态,像操作普通对象一样直接赋值即可触发更新。

ts
import reactive from "@yl_lowcode/reactive";

const store = reactive({ count: 0 });

// 读
console.log(store.count);

// 写(自动触发订阅组件重渲染)
store.count++;
store.count = 10;

跨组件共享

store 在模块作用域创建,天然实现跨组件状态共享——任意一处修改,所有订阅组件同步更新,无需 props 透传或 Context。

自动依赖追踪

useSnapshot() 返回的快照具备自动依赖追踪能力:解构了哪些 key 就只监听哪些 key,其余字段变化不触发当前组件重渲染。

tsx
// ✅ 只依赖 count,name 变化时此组件不重渲染
function CountPanel() {
  const { count } = store.useSnapshot();
  return <div>{count}</div>;
}

// ✅ 只依赖 name,count 变化时此组件不重渲染
function NamePanel() {
  const { name } = store.useSnapshot();
  return <div>{name}</div>;
}

注意:若直接使用整个快照对象(const snap = store.useSnapshot())而不解构,等价于订阅所有字段,任意字段变化都会触发重渲染。

嵌套对象深层响应

对嵌套对象属性直接赋值,无需手动触发更新,任意层级的修改都会自动冒泡到根 store 并通知订阅组件。

ts
const store = reactive({
  user: {
    name: "Alice",
    address: { city: "上海" },
  },
});

// ✅ 任意层级直接赋值,自动触发更新
store.user.name = "Bob";
store.user.address.city = "北京";

限制:深层响应仅对普通对象生效,ArrayMapSet 等容器类型的方法(如 pushset)不会自动触发更新,需替换整个引用:

ts
// ❌ push 不触发更新
store.list.push(1);

// ✅ 替换引用触发更新
store.list = [...store.list, 1];

重置初始状态

调用 store.restore() 将 store 的所有字段重置为初始值并触发视图更新。当所有订阅该 store 的组件全部卸载时,store 也会自动还原到初始状态,下次挂载时始终是干净的初始数据。

ts
// 手动重置
store.restore();

最佳实践

Store 定义建议放在模块顶层

ts
// store.ts
import reactive from "@yl_lowcode/reactive";

export const userStore = reactive({
  name: "",
  age: 0,
  role: "viewer" as "viewer" | "editor" | "admin",
});

按功能拆分多个 store

ts
// 避免一个巨大的全局 store,按功能域拆分
export const authStore = reactive({ token: "", userId: "" });
export const themeStore = reactive({ mode: "light", accent: "#6366f1" });
export const cartStore = reactive({ items: [] as CartItem[], total: 0 });

在事件处理函数中批量修改

ts
// 多次赋值会触发多次 dispatch,如需批量更新,建议直接替换对象
store.user = { ...store.user, name: "Bob", age: 25 };

API

reactive(initialState)

创建并返回一个响应式 store。

参数类型说明
initialStateTstore 的初始状态对象

返回值 T & { useSnapshot, restore }


store.useSnapshot()

React Hook,在组件中订阅 store,返回当前快照(浅冻结)。

  • 自动追踪本次渲染中访问过的 key,仅当这些 key 对应的值变化时才触发重渲染
  • 返回值顶层属性被 Object.freeze 保护,严格模式下直接修改会抛出运行时异常
  • 必须在 React 函数组件或自定义 Hook 内调用(遵循 React Hooks 规则)
ts
const { count, name } = store.useSnapshot();

store.restore()

将 store 重置为 reactive() 调用时传入的初始状态,并触发视图更新。

ts
store.restore();

内部保留属性

以下属性名为 store 内部保留,不可作为 state 的 key 使用:

属性名说明
state原始 state 对象
originStore初始状态快照(供 restore 用)
listeners订阅者集合
subscribe订阅方法
getSnapshot快照读取方法
dispatch内部触发更新方法
useSnapshotReact Hook
restore重置方法

TypeScript 会在编译期对使用保留名的 state key 进行报错提示。