restate / v1.0.0
快速开始
安装 restate,在组件之间共享第一个值,并在 React 之外使用同一个 store。
安装
restate 支持 React 16.8 及以上版本,自带 TypeScript 类型声明,没有其他运行时依赖。
npm install @kkwaenggwari/restate你的第一个共享状态
在组件外部创建一次 store。restate 返回的值既是 Hook,也是带有 set、get 等方法的对象。
Editor 和 CharacterCount 之间没有 props,也没有 Provider。在一个里输入,另一个就会更新。
import { restate } from '@kkwaenggwari/restate';
export const useDraft = restate('');
export function Editor() {
const text = useDraft();
return <textarea value={text} onChange={(event) => useDraft.set(event.target.value)} />;
}
export function CharacterCount() {
const count = useDraft((text) => text.length);
return <span>{count} characters</span>;
}更新值
set 接受一个新值,或一个基于旧值计算的函数。reset 回到你声明的初始值。
把值当作不可变数据:返回新的对象或数组,而不是修改旧的,这样 selector 才能察觉到变化。
你往 cart.items 里 push,再调用 useCart.set(cart)。为什么什么都没有重新渲染?
store 收到的是同一个对象,Object.is 判断没有变化。请返回一个新对象,例如 useCart.set(cart => ({ ...cart, items: [...cart.items, item] }))。
useCount.set(10); // replace the value
useCount.set((count) => count + 1); // compute from the previous value
useCount.reset(); // back to the declared initial value在 React 之外使用
同一个 store 也能用在事件处理函数、服务和测试中。get 读取当前值;subscribe 在每次变化后调用你,并返回一个停止监听的函数。
import { useCart } from './stores/cart';
// Any module, event handler or test can use the same store.
const current = useCart.get();
useCart.set((cart) => ({ ...cart, items: [...cart.items, 'Pen'] }));
const stop = useCart.subscribe((cart, previous) => {
console.log(previous.items.length, '→', cart.items.length);
});
stop();TypeScript
只需传一次状态类型,selector、set 和所有方法都会据此得到类型。
import { restate } from '@kkwaenggwari/restate';
type Cart = { items: string[]; coupon: string };
export const useCart = restate<Cart>({ items: [], coupon: '' });
const count = useCart((cart) => cart.items.length); // number
useCart.set((cart) => ({ ...cart, coupon: 'SPRING' }));React Native
在 React Native 上,内存 store 不需要任何额外配置。要保存状态,请安装 react-native-mmkv,React Native 入口会自动加载它。
对于 bare 项目,安装后请为 iOS 执行 pod install。在 Expo 中,由于 MMKV 是原生模块,请使用 development build。
npm install @kkwaenggwari/restate react-native-mmkv@4 react-native-nitro-modules所有平台,同一个声明
持久化 store 在浏览器中使用 IndexedDB,在 React Native 上使用 MMKV。声明和组件都保持不变。
import { persistedRestate } from '@kkwaenggwari/restate';
// IndexedDB on the web, MMKV on React Native. Same declaration.
export const useDraft = persistedRestate('', { key: 'draft' });