ilokesto

SSR and Initial State

How server snapshots work and why initial state matters.

SSR and Initial State

SSR support in @ilokesto/state is not bolted on afterward. It comes from the fact that the hook ultimately uses useSyncExternalStore, which asks for a server snapshot as well as a client snapshot.

The important distinction: current state vs initial state

At the store layer, those are not the same thing.

  • getState() is the current live value.
  • getInitialState() is the constructor-time value.

@ilokesto/state uses the second one for the server snapshot path.

Hydration shape

// server-side
const initialData = { count: 42 };

// client-side
const useCounter = create(initialData);

getServerSnapshot

Under the hood, the hook gives React store.getInitialState() as getServerSnapshot. That is what keeps the server-rendered tree aligned with the original store value during hydration.

This is also why mutating the store before React binds to it can change the feel of hydration in ways that are easy to miss.

Best Practices

  1. Create stores per request on the server so one user's state never leaks into another request.
  2. Hydrate from explicit initial data rather than depending on incidental client-side mutations.
  3. Be careful with persistence: persisted client state and server-provided initial state can disagree, and your app needs a clear precedence rule.
  4. Prefer explicit bootstrap points such as serialized data or a known initial store factory.

On this page