restate / v1.0.0
Get started
Install restate, share your first value between components, and use the same store outside React.
On this page
InstallYour first shared stateUpdate the valueUse it outside ReactTypeScriptReact NativeOne declaration on every platformInstall
restate works with React 16.8 and later. TypeScript declarations are included, and there are no other runtime dependencies.
npm install @kkwaenggwari/restateYour first shared state
Create the store once, outside your components. The value restate returns is both a hook and an object with methods such as set and get.
Editor and CharacterCount have no props or Provider between them. Typing in one updates the other.
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>;
}Update the value
set accepts a new value or a function of the previous value. reset returns to the value you declared.
Treat the value as immutable: return a new object or array instead of changing the old one, so selectors can see the change.
You push into cart.items and call useCart.set(cart). Why does nothing re-render?
The store receives the same object, and Object.is reports no change. Return a new object, for example 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 valueUse it outside React
The same store works in event handlers, services and tests. get reads the current value, and subscribe calls you after each change and returns a function that stops listening.
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
Pass the state type once. Selectors, set and every method are typed from it.
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
Memory stores need nothing else on React Native. To save state, install react-native-mmkv; the React Native entry loads it automatically.
For bare projects, run pod install for iOS after installing. In Expo, use a development build because MMKV is a native module.
npm install @kkwaenggwari/restate react-native-mmkv@4 react-native-nitro-modulesOne declaration on every platform
A saved store uses IndexedDB in the browser and MMKV on React Native. The declaration and your components stay the same.
import { persistedRestate } from '@kkwaenggwari/restate';
// IndexedDB on the web, MMKV on React Native. Same declaration.
export const useDraft = persistedRestate('', { key: 'draft' });