A few teammates who are newer to React tried my mini state library (react-state-custom) and got stuck before they even ran the examples. The library itself is just “write a hook, share it everywhere,” but the docs assumed you already loved custom contexts. So I spent the weekend gutting the README and rebuilding it for people who only know useState.
This post is a quick tour of what changed and why. I’d love feedback if you’re learning React state management or mentoring someone who is.
TL;DR
- Quick Start in 2 minutes: The README now opens with five numbered steps and a full code sample so you can go from plain hook → shared store → rendered component without jumping around.
- Core concepts in plain English: Follow the Quick Start with a “what the heck is going on?” section that explains contexts, publishers, subscribers, root factories, the auto manager, and the dev tool overlay—no EventTarget knowledge required.
- Copy/paste building blocks: Five tiny snippets (context, publisher, subscriber, root, auto) you can drop into any component file.
- Learning path: A four-step checklist (“follow the Quick Start → add smarter subscriptions → optimize → scale”) so you know what to try next.
-
API docs pointer:
API_DOCUMENTATION.mdnow starts with “read the Quick Start first” so new devs don’t get lost in type signatures.
Repo & docs: https://github.com/vothanhdat/react-state-custom
Demo playground: https://vothanhdat.github.io/react-state-custom/
What the new Quick Start looks like
Right under the install command you now see this flow:
- Write a plain hook (
useFeatureState). - Wrap it with
createRootCtx. - Hand the root to
createAutoCtxso<AutoRootCtx />can mount/dismount instances for you. - Mount
<AutoRootCtx />once near the top of your tree. - Call the generated hook wherever you want and destructure the data via
useQuickSubscribeoruseDataSubscribe*.
const useFeatureState = ({ featureId }: { featureId: string }) => {
const [value, setValue] = useState(0)
const double = useMemo(() => value * 2, [value])
return { value, double, increment: () => setValue(v => v + 1) }
}
const featureRoot = createRootCtx('feature', useFeatureState)
export const { useCtxState: useFeatureCtx } = createAutoCtx(featureRoot, 250)
function AppShell() {
return (
<>
<AutoRootCtx Wrapper={ErrorBoundary} debugging={import.meta.env.DEV} />
<Routes />
</>
)
}
function FeatureMeter({ featureId }: { featureId: string }) {
const ctx = useFeatureCtx({ featureId })
const { value, double, increment } = useQuickSubscribe(ctx)
return (
<section>
<strong>{value}</strong>
<em>{double}</em>
<button onClick={increment}>Add</button>
</section>
)
}
That’s the whole story. No reducers, no actions, no provider nesting.
Plain-language concepts + building blocks
Immediately after the example, the README explains the moving pieces:
-
Contexts on demand (memoized
EventTargets that auto-evict). - Publishers (effects that keep renders pure and guard against duplicates).
-
Subscribers (
useDataSubscribe*variants plus theProxy-powereduseQuickSubscribe). -
Root factories (
createRootCtxruns your hook once per parameter set). -
Auto orchestration (
AutoRootCtx+createAutoCtxmanage lifecycles). - Dev tooling (a dockable overlay driven by the memoized context cache).
Then you get five copy/paste snippets showing each primitive in isolation, so you can grab the one you need without rereading the Quick Start.
Advanced features when you need them
Once the basics click, the doc nudges you into:
-
DevTool overlay (now resizable with
@uiw/react-split, and you can passchildrento rename the toggle button). -
Parameterized contexts (one store per
listId,userId, etc.) with a reminder that props must be primitive for deterministic IDs. - Debounced or transformed subscribers for chatty data.
- Auto context grace periods (keep stores alive for X ms after the last subscriber unmounts).
Each example in src/examples/* mirrors this structure: a state.ts hook, app.tsx shell, and view.tsx UI that subscribes to the context. Yet more copy/paste fodder.
Learning path for new devs
I added a tiny callout so juniors know the intended order:
- Follow the Quick Start to build one shared store.
- Swap in the specific subscriber hooks where performance matters.
- Optimize (debounce, transform, AutoRoot cleanup delays).
- Scale out with parameterized contexts + DevTool overlay for visibility.
Looking for feedback
If you’re a new React dev—or you mentor folks who are—does this flow make state-sharing feel approachable? Where do you still stumble?
Help me make the docs even clearer:
- Repo: https://github.com/vothanhdat/react-state-custom
- Demo (with DevTool overlay): https://vothanhdat.github.io/react-state-custom/
Drop thoughts here or open an issue/PR if you notice something confusing. Thanks!
Top comments (0)