DEV Community

Cover image for I just rewrote my React state library docs for beginners—does the flow make sense?
Vo Thanh Dat
Vo Thanh Dat

Posted on

I just rewrote my React state library docs for beginners—does the flow make sense?

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.md now 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:

  1. Write a plain hook (useFeatureState).
  2. Wrap it with createRootCtx.
  3. Hand the root to createAutoCtx so <AutoRootCtx /> can mount/dismount instances for you.
  4. Mount <AutoRootCtx /> once near the top of your tree.
  5. Call the generated hook wherever you want and destructure the data via useQuickSubscribe or useDataSubscribe*.
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>
  )
}
Enter fullscreen mode Exit fullscreen mode

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 the Proxy-powered useQuickSubscribe).
  • Root factories (createRootCtx runs your hook once per parameter set).
  • Auto orchestration (AutoRootCtx + createAutoCtx manage 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 pass children to 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:

  1. Follow the Quick Start to build one shared store.
  2. Swap in the specific subscriber hooks where performance matters.
  3. Optimize (debounce, transform, AutoRoot cleanup delays).
  4. 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:

Drop thoughts here or open an issue/PR if you notice something confusing. Thanks!

Top comments (0)