create
Create a Store with Hooks for React applications, featuring built-in enhancers: withSubscribe, withUseSubscribe, withSnapshot, and withUseSnapshot. If you are looking for a Store without Hooks, please refer to createVanilla.
import { create } from '@shined/reactive';
const store = create(initialState);
// Usage example
const store = create({ count: 0});
store.mutate
store.restore()
store.snapshot()
store.useSnapshot()
store.subscribe()
store.useSubscribe()
store.mutate
Proxy state, of the same object type as the initial value, allows for modifying this object to change the Store's status.
// Usage example
store.mutate.count = 1;
store.mutate.count += 1;
store.mutate.inputValue = 'Hello';
store.mutate.info = { name: 'Shined', age: 18 };
store.mutate.info.hobbies.push('Coding');
store.snapshot
Retrieve a snapshot of the Store, available since v0.2.0
, supported by the built-in withSnapshot enhancer.
const snapSlice = store.snapshot(selector?);
// Usage example
const snap = store.snapshot();
const count = store.snapshot(s => s.count);
Related type definitions:
export interface WithSnapshotContributes<State extends object> {
/**
* Retrieves a snapshot of the state.
*/
snapshot: <StateSlice = State>(selector?: SnapshotSelector<State, StateSlice>) => StateSlice
}
export type SnapshotSelector<State, StateSlice> = (state: State) => StateSlice
store.useSnapshot
Retrieve a snapshot of the Store in a React component, supported by the built-in withUseSnapshot enhancer.
store.useSnapshot(selector?);
store.useSnapshot(options?);
store.useSnapshot(selector?, options?);
// Usage example
const snap = store.useSnapshot();
const count = store.useSnapshot(s => s.count);
const syncSnap = store.useSnapshot({ sync: true });
const syncValue = store.useSnapshot(s => s.inputValue, { sync: true });
Related type definitions:
export interface WithUseSnapshotContributes<State extends object> {
/**
* Retrieves a snapshot of the state.
*/
useSnapshot: StoreUseSnapshot<State>
}
export type SnapshotSelector<State, StateSlice> = (state: State) => StateSlice
export interface StoreUseSnapshot<State> {
(): State
(options: SnapshotOptions<State>): State
<StateSlice>(selector: SnapshotSelector<State, StateSlice>): StateSlice
<StateSlice>(selector: undefined, options: SnapshotOptions<StateSlice>): State
<StateSlice>(selector: SnapshotSelector<State, StateSlice>, options: SnapshotOptions<StateSlice>): StateSlice
}
export interface SnapshotOptions<StateSlice> {
/**
* Whether to notify updates synchronously, default is false, i.e., asynchronous batch updates to enhance performance.
*
* In some scenarios, such as using a Chinese input method in a text field, you may need to get the latest state immediately. Set this to true in those cases.
*
* @defaultValue false
*/
sync?: boolean
/**
* Custom equality function used to compare the previous and next state slices.
*
* @defaultValue Object.is
*/
isEqual?: (a: StateSlice, b: StateSlice) => boolean
}
store.subscribe
Subscribe to changes in the Store, supported by the built-in withSubscribe enhancer, not recommended unless necessary.
store.subscribe(listener, notifyInSync?, selector?);
// Usage example
store.subscribe(() => {
console.log(store.snapshot());
});
const unsubscribe = store.subscribe(() => {
console.log(store.snapshot());
}, true);
// Unsubscribe
unsubscribe()
Related type definitions:
export interface WithSubscribeContributes<State extends object> {
/**
* Subscribe to changes in the Store's state.
*
* @param listener - The callback function to subscribe.
* @param sync - Whether to notify updates synchronously, default is false, for performance through asynchronous batch updates.
* @param selector - Selector for the state slice to listen for changes.
*/
subscribe: (listener: SubscribeListener<State>, sync?: boolean, selector?: (state: State) => object) => () => void
}
export type ChangeItem<State> = {
props: PropertyKey[] // ['a', 'b', 0, 'c']
propsPath: string // 'a.b[0].c'
previous: unknown
current: unknown
snapshot: State
}
export type SubscribeListener<State> = (changes: ChangeItem<State>, version?: number) => void
store.useSubscribe
Subscribe to changes in the Store within React components, subscribing to changes upon component mount and unsubscribing on component unmount, supported by the built-in withUseSubscribe enhancer, not recommended unless necessary.
If you need to perform some side effects based on state changes, useUpdateEffect is preferred over this method.
const count = store.useSnapshot(s => s.count);
// Execute side effects when count changes
useUpdateEffect(() => {
console.log('Count has changed', count);
}, [count]);
store.useSnapshot(listener, options?);
// Usage example, prefer using useUpdateEffect
store.useSubscribe(() => {
console.log('Store has changed');
});
store.useSubscribe(changes => {
console.log('Store has changed', changes);
});
store.useSubscribe(() => {
console.log('Store has changed');
}, { sync: true });
Related type definitions:
export interface WithUseSubscribeContributes<State extends object> {
/**
* Subscribe to changes in the Store within React components.
*
* @param listener - The subscription callback function.
* @param notifyInSync - Whether to notify updates synchronously, default is false, for asynchronous batch updates enhancing performance.
*/
useSubscribe: (listener: SubscribeListener<State>, notifyInSync?: boolean) => void
}
store.restore
Restore the Store to its initial state.