Skip to content
react-global-state-hooks

Scoped state with createContext

Give each part of the tree its own store with the same selector and action API as global state.

GuideTypeScriptTry an example
Provider A
name: “Ada”
Provider B
name: “Grace”

Same component. Independent store instances.

The problem this solves

A form, a wizard or a list row needs state that several components share, but that must not leak to the rest of the app or to another instance of itself. createContext creates a store per Provider.

Create and use a context

counter-context.tsx
import { createContext } from 'react-global-state-hooks';

export const CounterContext = createContext(
  { count: 0 },
  {
    actions: {
      increment(by = 1) {
        return ({ setState }) => {
          setState((state) => ({ count: state.count + by }));
        };
      },
    },
  },
);

export function Counter({ label }: { label: string }) {
  // Reads the closest CounterContext.Provider above this component.
  const [count, actions] = CounterContext.use((state) => state.count);

  return (
    <button onClick={() => actions.increment()}>
      {label}: {count}
    </button>
  );
}

export function TwoCounters() {
  // Each Provider creates its own independent store.
  return (
    <>
      <CounterContext.Provider>
        <Counter label="left" />
      </CounterContext.Provider>
      <CounterContext.Provider value={{ count: 10 }}>
        <Counter label="right" />
      </CounterContext.Provider>
    </>
  );
}

createContext(initialState, options?) returns { use, Provider, Context }. It supports the same options as a global store except persistence: actions, metadata, name and callbacks.

Provider values

Provider propResult
noneThe store starts from the context’s initial state.
value={x}The store starts from x, and follows x when it changes.
value={(initial) => ...}The function runs once to create the initial state. It receives the context’s initial state, not the value of a parent provider.

Reading from a context

CallReturns
Ctx.use(selector?, deps?)The same tuple as a store hook.
Ctx.use.select(selector)Just the selected value.
Ctx.use.api()The store API for the closest provider (getState, setState, subscribe, …).
Ctx.use.actions()The closest provider’s actions object.
Ctx.use.observable(selector)A memoised observable for the closest provider.
Ctx.use.createSelectorHook(selector)A shared, chainable selector hook for this context.

Ctx.use throws use hook must be used within a ContextProvider when there is no provider above it.

Lifecycle callbacks

Set callbacks on the context or onCreated / onMounted on a single Provider. onMounted may return a cleanup function that runs on unmount.

What to watch for

  • Each mounted Provider is a new store. Remounting a provider resets its state.
  • Persistence to localStorage is a feature of global stores, not of contexts.
Documentation
↑↓ Navigate ↵ Open Esc CloseRGSH docs
Get started

Shared state. Precise subscriptions.
Built-in DevTools.