A tiny, framework-agnostic state store for the web. Simple, reactive, and immutable. Works with everything.
structuredClone
if available, falls back to JSON.parse(JSON.stringify(...))
to ensure state updates are truly immutable.get
, set
, and subscribe
.Method | Description |
---|---|
get() |
Returns the current state. |
set((state) => {}) or set(value) |
Replaces the state. Accepts either a new state or an updater function that returns new state. |
subscribe((state => {})), false) |
Subscribes a listener function to state changes. Returns an unsubscribe function. Setting false to true will run the listener instantly. |
eis(null, {"dev": false}) |
Default exported function the first argument takes your inital state (uses set ) and the second is an optional configuration object that can be used to set developer mode to false disabling freezing and cloning for better performance. Returns an array of functions (get, set, subscribe). |
InitError
if initialState
is undefined, defaulting to null.TypeError
if an invalid object (e.g., string, number, null) is passed to _freeze
, expecting a plain object or array.CloneError
if an object or array cannot be cloned due to non-serializable data (e.g., functions, Date objects, circular references).SetError
if set is called with undefined.NoOp
warning if an updater function returns undefined.SubscribeError
if a non-function is passed to subscribe, ignoring the subscription.npm install @taujor/eis
or
yarn add @taujor/eis
Via CDN:
import eis from 'https://unpkg.com/@taujor/eis/eis.js'
Or include directly in your project:
import eis from '@taujor/eis'
import eis from '@taujor/eis';
const [get, set, subscribe] = eis({ count: 0 });
// Subscribe to state changes
const unsubscribe = subscribe((state) => {
console.log('State changed:', state);
}, true);
// Update state
set({ count: 1 });
// Logs: State changed: { count: 1 }
set((state) => ({ count: state.count + 1 }));
// Logs: State changed: { count: 2 }
// Get current state
console.log(get());
// { count: 2 }
// Unsubscribe
unsubscribe();
import { useEffect, useState } from 'react';
import eis from '@taujor/eis';
// Initialize the state store with a number
const [get, set, subscribe] = eis(0);
function Counter() {
// Use React state to trigger re-renders
const [count, setCount] = useState(get());
// Subscribe to eis state changes
useEffect(() => {
const unsubscribe = subscribe((newState) => {
console.log('Count:', newState);
setCount(newState); // Update React state
}, true); // Immediate invocation to sync initial state
return unsubscribe; // Cleanup on unmount
}, []);
return (
<div style={{ padding: '20px' }}>
<h1>Simple Counter</h1>
<p>Count: {count}</p>
<button
onClick={() => set((state) => state + 1)}
style={{ marginRight: '10px' }}
>
Increment
</button>
<button
onClick={() => set((state) => state - 1)}
>
Decrement
</button>
</div>
);
}
export default Counter;
JSON.parse(JSON.stringify(...))
does not handle non-serializable objects so for consistency non-serializable objects are also rejected when using structuredClone
.eis(null, {dev: false})
Contributions are welcome! Please open an issue or submit a pull request.
If you're using eis.js why not show off about it? Let everyone know in the dedicated discussion