A lightweight, proxy-based global state management library for React.
- Lightweight: Minimal footprint with zero dependencies beyond React
- Proxy-based: JavaScript Proxy enables nested property access with path tracking
- Dynamic Scoping: Components automatically subscribe only to specific array indices or object properties they access
npm install @longsien/react-store
import { store, useStore } from '@longsien/react-store'
// Create a store
const counterStore = store(0)
function Counter() {
const [count, setCount] = useStore(counterStore)
return (
<div>
<p>Count: {count}</p>
{/* Increment Set value directly */}
<button onClick={() => setCount(count + 1)}>+</button>
{/* Use updater function for synchronous updates */}
<button onClick={() => setCount(prev => prev - 1)}>-</button>
</div>
)
}
Creates a basic in-memory store that persists for the lifetime of the application session.
const userStore = store({ name: 'Winter', age: 24 })
Creates a store backed by localStorage with automatic persistence. Data is automatically serialized to JSON when saving and deserialized when loading.
const settingsStore = store({ theme: 'dark' }).local('settings')
Creates a store backed by sessionStorage with automatic persistence. Data is automatically serialized to JSON when saving and deserialized when loading.
const tempStore = store({ items: [] }).session('temp-data')
Returns [value, setState]
tuple for reading and updating state. Use exactly the same as React's built-in useState
hook.
const [user, setUser] = useStore(userStore)
const [userName, setUserName] = useStore(userStore.name)
const [userEmail, setUserEmail] = useStore(userStore.contact.email)
Returns only the current value (read-only).
const user = useStoreValue(userStore)
const userName = useStoreValue(userStore.name)
Returns only the setter function, avoiding unnecessary re-renders when the value changes.
const setUser = useStoreSetter(userStore)
const setUserName = useStoreSetter(userStore.name)
Get current value outside React components. Useful for utility functions, event handlers, or any code that runs outside the React render cycle.
const currentUser = userStore.get()
const useName = userStore.name.get()
Update value outside React components. Triggers all subscribed components to re-render if their specific data has changed. Accepts the same value types as the hook-based setters.
useStore.set({ name: 'Karina', age: 25 })
useStore.name.set('Karina')
useStore.age.set(prev => prev + 1)
The library uses JavaScript Proxies to enable nested property access. This allows components to subscribe to deeply nested values without re-rendering when unrelated parts of the state change.
const userStore = store({
profile: { name: 'Winter', settings: { theme: 'dark' } },
posts: [],
})
// Access nested values - each creates a scoped subscription
const [theme, setTheme] = useStore(userStore.profile.settings.theme)
const [posts, setPosts] = useStore(userStore.posts)
// Update nested values immutably
setTheme('light') // Only components using userStore.profile.settings.theme re-render
setPosts(prev => [...prev, newPost]) // Only components using userStore.posts re-render
Nested property access works with dynamic scoping, allowing dynamic path path subscription based on component props.
const [comment, setComment] = useStore(commentsStore[index])
const author = useStoreValue(commentsStore[index].author)
const [user, setUser] = useStore(usersStore[userId])
const setStatus = useStoreSetter(usersStore[userId].status)
- React 18.0.0 or higher
MIT
Issues and pull requests are welcome on GitHub.
Long Sien