Skip to Content
useS v2.4.0 is released 🎉
DocsAPIAPI Reference

API Reference

The useS hook offers a powerful yet minimal API to manage both local and global state in React — with built-in immutability and TypeScript support.

  • State type is automatically inferred from the initialValue.
  • Supported types: null | undefined | number | string | boolean | bigint | function | asyncfunction | date | regexp | array | set | map | object.

🧠 useS(initialValue: T)

Creates a local state, just like useState, but with enhanced capabilities:

const [state, setState] = useS(0);

🌍 useS({ value: T; key: string; })

Creates a global state shared across all components using the same key.

const [count, setCount] = useS({ value: 0, key: "global-counter", });

This is functionally identical to local state, but allows cross-component sharing.

🔑 Global State Rules

  • key must be a non-empty unique string.
  • The first call to useS() with a given key sets the initial value.
  • All subsequent calls with the same key:
    • Ignores the creation of a new state.
    • Share the same state.
  • This ensures state consistency without conflicts or duplication — regardless of where or how many times the key is used.

💿 Persistence { ..., persist?: bolean; }

Starting with version 2.3.0 of use-s-react, a third optional parameter was added to the global state configuration object called persist:

const [count, setCount] = useS({ value: 0, key: "global-counter", persist: true });
  • When persist is set to true, you are telling useS to use the browser’s localStorage to read any initial value stored there and assign it to the initial value of the state that already exists, along with any valid changes, before creating the global state for the first time.
  • In addition will save the change asynchronously in localStorage every time setState is executed without blocking the main thread.
  • It will allow you, as a developer, to choose which global states you want to save and which you don’t.
  • Facilitates debugging by using the same key for the global state in localStorage.
  • This is a completely optional parameter and does not affect any previous functionality.

🧬 Built-In Immutability

  • Immutability at entry: useS does not work on the memory reference of the initialValue, it only clones it and creates the state.
  • Immutability at exit: useS returns a clone of the actual state, which can be mutated from the component, and this mutation does not affect the original state.

With useS, you will always respect React’s rule of not mutating state because it lets you do so without consequences and then allows you to use that mutation to update it with setState without risk:


Component.tsx
const initialValue = new Set([1, 2, 3, 4]); export function Component() { const [mySet, setMySet] = useS(initialValue); const handleAddItem = () => { mySet.add(5); // mutating mySet state directly setMySet(mySet); // setting the mutated state to generate a valid change }; return ( <div> <p data-testid="display">Items:{Array.from(mySet).join("-")}</p> <button onClick={handleAddItem}>Add Item</button> </div> ); }

🔍 Intelligent Validation and Render Prevention

One of the most powerful optimizations in useS is its ability to prevent unnecessary re-renders through structural comparison between the previous and the next value. This means that if the new value is not different or is not supported, the state will not be updated and the component will not be re-rendered.

How Does It Work?

Internally, useS uses a comparison function based on the data type. Each supported type has its own mechanism to determine whether a change is valid:

Value TypeComparison Strategy
AllObject.is(a, b).
DateCompares timestamps using getTime().
RegExpCompares source and flags.
SetRecursively compares each value.
MapRecursively compares each key and value.
ArrayRecursively compares each element.
ObjectRecursively compares keys and values, including nested ones.

This allows you to handle complex structures without external libs or manual hacks like JSON.stringify.

⚠️ Exceptions

  • Functions:

Although you can include functions as part of your state these are compared by reference. Every time a key is updated with a function value, it is likely to trigger a state update and re-render.

This behavior is consistent with how React handles functions.

  • Initialization values: null | undefined | [] | {} | new Set() | new Map()

The validation function recognizes the previous common initialization values, allowing them to be assigned to the state. In addition, if the previous value is one of these, it allows the next value to be assigned to the state, checking that it is a compatible value.


Summary

FeatureStatusNotes
Local state✅ CompleteSame API as useState
Global state✅ CompleteShared by key, no Provider required
TypeScript support✅ CompleteFully inferred, no manual typing needed
Automatic immutability✅ CompleteDeep cloning at the entrance and exit
Avoid Unnecessary re-renders✅ CompleteReference or deep value comparison with type validation
Derived state support✅ CompleteSupports computed state via function properties
React 18 compatibility✅ CompleteUses useSyncExternalStore
Web & React Native✅ CompleteCompatible with both
Bundle size✅ Small22.9kB Unpacked Size
Boilerplate-free✅ CompleteNo context, no Provider, no setup
Built-in persistence✅ CompleteAllows you to save and read the global state in localStorage
DevTools/debugging⚠️ PartialdebugGlobalStore() available via console

Would you like to learn more?

Explore Hook Config to see how you can have complete control over what useS does under the hood.

Last updated on