Skip to Content
useS v2.1.0 is released 🎉
DocsAPI

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 | 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.

🧬 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
DevTools/debugging⚠️ PartialdebugGlobalStore() available via console
Built-in persistence❌ Not yetPlanned for future versions

Ready to see it in action? Explore real-world Examples to see how useS can simplify your components.

Last updated on