Quick Start
React Concurrent Store is a ponyfill that brings the experimental React concurrent store API to React 19+. It allows you to manage async resources with proper handling for non-blocking updates.
Installation
Section titled “Installation”-
Install the package
Terminal window npm install https://pkg.pr.new/thejustinwalsh/react-concurrent-store@7e8861dTerminal window yarn add https://pkg.pr.new/thejustinwalsh/react-concurrent-store@7e8861dTerminal window pnpm add https://pkg.pr.new/thejustinwalsh/react-concurrent-store@7e8861dTerminal window bun add https://pkg.pr.new/thejustinwalsh/react-concurrent-store@7e8861d -
Import the hooks
import { createStore, useStore } from "react-concurrent-store"; -
Create your first store
// Create a simple store with initial dataconst counterStore = createStore(0);// Or create a store with async dataconst fetchUser = async (id: number) => {const response = await fetch(`/api/users/${id}`);return response.json();};const userStore = createStore(fetchUser(1)); -
Use the store in your components
import { Suspense, use } from "react";function Counter() {const count = useStore(counterStore);return (<div><p>Count: {count}</p><button onClick={() => counterStore.update(count + 1)}>Increment</button></div>);}function UserProfile() {const userPromise = useStore(userStore);const user = use(userPromise); // Suspend until resolvedreturn (<div><h1>{user.name}</h1><p>{user.email}</p></div>);}function App() {return (<div><Counter /><Suspense fallback={<div>Loading user...</div>}><UserProfile /></Suspense></div>);}
Key Concepts
Section titled “Key Concepts”Stores
Section titled “Stores”Stores are containers that hold values or promises. They can be updated reactively and integrate seamlessly with React’s concurrent features.
Updates
Section titled “Updates”Use useTransition to wrap the update action in a transition and track the action’s isPending state.
The store will always execute the update in an action, even if the update is not wrapped in a transition.
import { useTransition } from "react";
function UserProfile() { const userPromise = useStore(userStore); const user = use(userPromise); const [isPending, startTransition] = useTransition();
const loadNextUser = () => { startTransition(() => { userStore.update(fetchUser(user.id + 1)); }); };
return ( <div style={{ opacity: isPending ? 0.5 : 1 }}> <h1>{user.name}</h1> <button onClick={loadNextUser}>Next User</button> </div> );}Suspense Integration
Section titled “Suspense Integration”Stores containing promises automatically integrate with React Suspense by passing the store result to the use hook.
When the store is updated as an Action within a non-blocking Transition, the store will properly update the state without de-opting to a synchronous update.