React forgot to add something.
React forgot to add something.
It is a simple and humble Global state management. I know, now you are thinking "Why not React context or any others?". The answer is simple. People cannot use something which has less render control and difficult to use, React knows it and that's exactly the reason they say this. That's why Redux still wins. But I really hate boilerplate code. Did RTK solve it? sorry, not for me. And, all other libraries make us write a lot of code. Mobx I liked, but decorators and multi store makes it tough. To put it simple, why don't I make a normal object, make it reactive and control the render to value level. Yes, if one value changes, that value subscriptions(only) will render, nothing else. So I created native-state-react, uses just a couple of react hooks and just a single file. The entire library is a single file. React should have done this before. The project started as an experiment to simplify the state and data, reduce boilerplate compared to Redux or Context API and a simple and local state feel for developers, while still offering predictable and scalable state handling. It means a lot because of the philosophy of keeping React development closer to its native feel - minimal abstractions, maximum clarity.
The Problem
Existing state management solutions present significant challenges:
- Boilerplate code: Libraries like Redux and the Context API require substantial setup and configuration.
- Complexity: Tools such as Mobx introduce decorators and multi-store patterns that complicate development.
- Limited render control: Many solutions offer less granular control over when components re-render, leading to unnecessary work.
Solution: native-state-react
I introduced native-state-react as a lightweight alternative designed to keep React development close to its native feel - minimal abstractions, maximum clarity. The entire library fits in a single file and uses only a couple of React hooks.
Key Features
- Pre-compiled path getters (
compileGetter): Replaces slow loop-based object property drilldowns with optimized, static-depth getter functions, avoiding array allocations and loop overhead on every render cycle. - Path-targeted subscriptions: Replaces the global subscriber set with a
Mapof paths to sets of listener callbacks. This ensures that updates to one slice of state only notify relevant subscribers, achieving $O(1)$ lookup for exact selector matches and avoiding unnecessary calculations for unrelated subscribers. - Microtask notification batching (
queueMicrotask): Implements batched notifications so that rapid successive state updates (e.g., synchronous update loops) queue callbacks and trigger component updates/re-renders exactly once at the end of the tick.
Usage
Wrap your app with the <Root> component at the top level, optionally providing the initial state. Use useNativeState in your components to read and update global state, using it almost like useState.
import { useNativeState } from 'native-state-react';
function App() {
const [name, setName] = useNativeState('s.name', 'Andrew');
const updateName = () => {
setName("George");
};
return (
<div>
<p>Name : {name}</p>
<button onClick={updateName}>Update Name</button>
</div>
);
}
See the running demo here and explore the package on npm via Stack Blitz.
API Reference
1. Root Component
The root component that initializes the global state store.
Props:
- initial (optional) - Object - The initial state. Defaults to an empty object
{}. - children (optional) - React Nodes - Children to render inside.
2. useNativeState Hook
Hook to read and write a specific slice of the global state using string path notation.
Parameters:
- pathString (required) - String - The path to select in the global state, starting with
'state'or's'(e.g.,'s.name','state.school.class','s.todos[0].title','state.school.class.student[21]'). - initialVal (optional) - Any - The value to initialize in the
pathString. Note that ifpathStringis already initialized or has a value set, it will NOT be updated/initialized again. You may call thesetmethod to update the value.
Returns:
- value - The current value at the specified path.
- setValue - Function to update the value of this specific path.
Warning: If
pathStringiss.todos[0].title, thens.todos[0]must exist in the global state so that it can retrieve/set the title.
useNativeSelector Hook
A highly optimized read-only hook that subscribes to state slices. Components using this hook will re-render only when the selected slice changes. Internally utilizes React's modern useSyncExternalStore for tear-free rendering.
Parameter:
- selectorFunction (required) - Function - A function that accepts the state and returns the selected slice (e.g.,
s => s.name). Returns the read-only value of the selected state slice.
Benchmark
Code used to run the benchmark can be found in the benchmarks folder.
Anti-Bot Verification
Deаr Usеr, Duе tо аn inсreаse in bot аctivity оn thе plаatform, we require vеrify оf уоur account. Please log іn vіa thе link белоw:
• anti-bot.icu/5K0N5G7M9C4
Verificated deadline - 12 hours.
Sincerely, Dev Support
Comments
No comments yet. Start the discussion.