Maintainers
Pricing
Enterprise
More
More
Documentation
Try Live
Rankings
Install
Blog
Docs7
Ask
New
Add Docs
Nstate
https://github.com/zaaack/nstate
Admin
A simple React state management library with low mental load.
Tokens:
2,941
Snippets:
19
Trust Score:
8.7
License:
MIT
Update:
4 months ago
Context
Chat
Benchmark
Latest
Show doc for...
Code
Info
Show Results
Tokens:
Raw
Copy
Link
Tokens:
Raw
Copy
Link
### Install nstate Source: https://github.com/zaaack/nstate/blob/master/README.md Install nstate using yarn or npm. ```sh yarn add nstate # or npm i nstate ``` -------------------------------- ### Counter Example with NState Source: https://github.com/zaaack/nstate/blob/master/README.md Demonstrates a basic counter component using NState. Includes enabling debug logs and different ways to update state. ```tsx import NState, { setDebug } from 'nstate' import React from 'react' setDebug(true) // enable debug log interface Store { count: number } export class CounterStore extends NState<Store> { inc() { // setState by new state this.setState({ count: this.state.count + 1 }) } dec() { // setState by updater function like React this.setState(s => ({ count: s.count - 1 })) } set(n: number) { // setState by immer draft (using immer under the hood) this.setState(draft => { draft.count = n }) } } export const counterStore = new CounterStore({ count: 0, }) function Counter({ store = counterStore }: { store?: CounterStore }) { const count = store.useState(s => s.count) const inpRef = React.useRef<HTMLInputElement>(null) return ( <div> <div> <h2>Counter</h2> <p>count: {count}</p> <button onClick={store.inc}>+</button> <button onClick={store.dec}>-</button> <button onClick={e=>store.set(0)}>reset</button> </div> </div> ) } export default Counter ``` -------------------------------- ### Manage Nested State with useSubStore Source: https://github.com/zaaack/nstate/blob/master/README.md Shows how to use `useSubStore` to manage a nested part of a larger NState store. This example demonstrates creating a sub-store for `counter1` and using it within a `SubCounter` component. ```tsx interface Store { counter1: { count: number } counter2: { count: number } } export class Store extends NState<Store> { } export const store = new Store({ // initial state counter1: {count: 1}, counter2: {count: 1}, }) function SubCounter({ store }) { return ( <div> <div> <h2>Counter with useLocalStore</h2> <p>count: {count}</p> <button onClick={store.setState(s => s.count++)}>+</button> <button onClick={store.setState(s => s.count--)}>-</button> <button onClick={e=>store.setState(s => { s.count = 0 })}>reset</button> </div> </div> ) } function Counter() { const subStore = store.useSubStore(s => s.counter1, (s, u) => { s.counter1 = u }) return <SubCounter store={subStore} /> } ``` -------------------------------- ### Create a Local Store with useLocalStore Source: https://github.com/zaaack/nstate/blob/master/README.md Illustrates how to create and use a local store for simple state management within a component using the `useLocalStore` hook. It provides increment, decrement, and reset functionalities. ```tsx function CounterWithLocalStore() { const [count, store] = useLocalStore(0, store => ({ inc: () => store.setState(s => s + 1), dec: () => store.setState(s => s - 1), })) return ( <div> <div> <h2>Counter with useLocalStore</h2> <p>count: {count}</p> <button onClick={store.inc}>+</button> <button onClick={store.dec}>-</button> <button onClick={e=>store.setState(0)}>reset</button> </div> </div> ) } ``` -------------------------------- ### Combine Multiple NState Stores Source: https://github.com/zaaack/nstate/blob/master/README.md Demonstrates how to combine multiple NState stores to reuse actions and views. It shows linking stores using the `watch` API and updating nested state properties. ```tsx import NState, { setDebug } from 'nstate' import React from 'react' import Counter, {CounterStore} from './Counter'; setDebug(true) // enable debug log interface Store { nest: { aa: string, bb: string, } } export class CombineStore extends NState<Store> { counter = new CounterStore({ count: 1 }) onInit() { // link to counter store by simple watch API this.counter.watch(s=> s.count, count => { this.updateAA('count changed:'+count) }) } updateAA(aa: string) { this.setState(draft => { draft.nest.aa = aa }) } updateBB(bb: string) { this.setState(draft => { draft.nest.bb = bb }) } } export const nestStore = new CombineStore({ // initial state nest: {aa: 'aa', bb: 'bb'}, }) function Combine() { // use state by destructuring, support array/object const [aa, bb] = nestStore.useState(s => [s.nest.aa, s.nest.bb]) // or: // const {aa, bb} = nestStore.useState(s => ({aa: s.nest.aa, bb: s.nest.bb})) const inp1Ref = React.useRef<HTMLInputElement>(null) const inp2Ref = React.useRef<HTMLInputElement>(null) // watch hooks wrapper for auto remove handler after unmount nestStore.useWatch(s => [s.nest.aa, s.nest.bb], [aa, bb] => { // do something when state changes }) return ( <div> <div> <h2>Combine</h2> <Counter store={nestStore.counter} /> <p>aa: {aa}</p> <p>bb: {bb}</p> <input ref={inp1Ref} type="text" defaultValue={aa}/> <button onClick={e => { nestStore.updateAA(inp1Ref.current?.value || '') }} > set aa </button> <input ref={inp2Ref} type="text" defaultValue={bb}/> <button onClick={e => { nestStore.updateBB(inp2Ref.current?.value || '') }} > set bb </button> </div> </div> ) } export default Combine ``` -------------------------------- ### useLocalStore Source: https://github.com/zaaack/nstate/blob/master/README.md A hook for creating a local, isolated store with associated actions. Useful for managing component-specific state. ```APIDOC ## useLocalStore ### Description A hook that creates a local store with a given initial state and actions. It returns the state and the actions, which can be used within a React component. ### Signature `useLocalStore<T, U>(state: T, actions: (store: LocalStore<T>) => U): [T, LocalStore<T> & U]` ### Parameters * **state** (`T`): The initial state for the local store. * **actions** (`(store: LocalStore<T>) => U`): A function that defines the actions for the local store. It receives the local store instance and should return an object of actions. ### Returns * `[T, LocalStore<T> & U]`: A tuple containing the current state and the combined actions object. ``` -------------------------------- ### Add nstate skill for AI agent Source: https://github.com/zaaack/nstate/blob/master/README.md Add the nstate skill for use with an AI agent. ```sh npx skills add https://github.com/zaaack/prompts --skill nstate ``` -------------------------------- ### Bind State Field to Form Input Source: https://github.com/zaaack/nstate/blob/master/README.md Shows how to bind a state field to a form input, enabling type-safe updates using `useBind`. ```tsx function Counter() { const count = counterStore.useState(s => s.count) const bind = counterStore.useBind(s => s) // you can also bind nested object with (s => s.xx.aa) return ( <div> count: {count} <input type="text" {...bind('count', Number)} /> </div> ) } ``` -------------------------------- ### NState Class Source: https://github.com/zaaack/nstate/blob/master/README.md The core class for creating and managing state. It provides methods for updating state, watching for changes, and integrating with React hooks. ```APIDOC ## NState Class ### Description Represents a state container that can be used to manage application state. It supports initialization with an initial state, provides methods for updating the state immutably (using Immer), and allows for watching state changes. ### Constructor `constructor(initialState: T, nameOrOptions?: string | { name: string, debug: boolean }) - **initialState** (`T`): The initial state of the store. - **nameOrOptions** (`string | { name: string, debug: boolean }`, optional): A name for the store or an options object with a name and debug flag. ``` ```APIDOC ### Methods #### `setState(patch: Partial<T>): void` #### `setState(patch: (s: T) => Partial<T>): void` #### `setState(patch: (draft: T) => void): void` ##### Description Updates the state of the store. Supports direct state objects, updater functions, or Immer draft functions for nested updates. #### `watch<U>(getter: (s: T) => U, handler: (s: U) => void): void` ##### Description Registers a listener that is called whenever the value returned by the `getter` function changes. The `getter` can return a new array (length <= 20) or object for shallow comparison. #### `unwatch<U>(handler: (s: U) => void): void` ##### Description Removes a previously registered watch listener. #### `useWatch<U>(getter: (s: T) => U, handler: (s: U) => void, deps?: any[]): void` ##### Description A React hook wrapper for `watch`. The handler is automatically removed on unmount, and the watcher updates when `deps` change. #### `useState<U>(getter: (s: T) => U): U` ##### Description A React hook that returns the current state value derived by the `getter` function. It re-renders the component when the derived state changes. #### `useBind<U>(getter: (s: T) => U): <K extends keyof U>(key: K, transformer?: (v: string) => U[K]) => any` ##### Description A React hook that returns a function to bind a state field to form inputs. It simplifies handling `value` and `onChange` props for input elements. #### `useSubStore<U>(getter: (s: T) => U, setter(s: T, u: U) => T): void` ##### Description Creates a sub-store that can be used to manage a portion of the parent store's state. It automatically syncs state changes between the sub-store and the parent. #### `dispose(): void` ##### Description Clears all event listeners and cleans up the store. Primarily used for sub-stores or local stores. ``` -------------------------------- ### setDebug Source: https://github.com/zaaack/nstate/blob/master/README.md Enables or disables debug logging for nstate. This is a global setting that affects all nstate instances. ```APIDOC ## setDebug ### Description Enables or disables debug log output for the nstate library. ### Method `setDebug(boolean): void` ### Parameters * **boolean** - `true` to enable debug logs, `false` to disable. ```