Back to Jotai

SSR

docs/utilities/ssr.mdx

2.19.12.5 KB
Original Source

useHydrateAtoms

Ref: https://github.com/pmndrs/jotai/issues/340

Usage

js
import { atom, useAtom } from 'jotai'
import { useHydrateAtoms } from 'jotai/utils'

const countAtom = atom(0)
const CounterPage = ({ countFromServer }) => {
  useHydrateAtoms([[countAtom, countFromServer]])
  const [count] = useAtom(countAtom)
  // count would be the value of `countFromServer`, not 0.
}

The primary use case for useHydrateAtoms are SSR apps like Next.js, where an initial value is e.g. fetched on the server, which can be passed to a component by props.

⚠️ Note: Although the term "hydrate" might suggest server-side usage, this hook is designed for client-side code and should be used with the 'use client' directive.

ts
// Definition
function useHydrateAtoms(
  values: Iterable<readonly [Atom<unknown>, unknown]>,
  options?: { store?: Store },
): void

The hook takes an iterable of tuples containing [atom, value] as an argument and optional options.

js
// Usage with an array, specifying a store
useHydrateAtoms(
  [
    [countAtom, 42],
    [frameworkAtom, 'Next.js'],
  ],
  { store: myStore },
)
// Or with a map
useHydrateAtoms(new Map([[count, 42]]))

Atoms can only be hydrated once per store. Therefore, if the initial value used is changed during rerenders, it won't update the atom value. If there is a unique need to re-hydrate a previously hydrated atom, pass the optional dangerouslyForceHydrate as true and note that it may behave wrongly in concurrent rendering.

js
useHydrateAtoms(
  [
    [countAtom, 42],
    [frameworkAtom, 'Next.js'],
  ],
  {
    dangerouslyForceHydrate: true,
  },
)

If there's a need to hydrate in multiple stores, use multiple useHydrateAtoms hooks to achieve that.

js
useHydrateAtoms([
  [countAtom, 42],
  [frameworkAtom, 'Next.js'],
])
useHydrateAtoms(
  [
    [countAtom, 17],
    [frameworkAtom, 'Gatsby'],
  ],
  { store: myStore },
)

If you are using TypeScript with target ES5, you might need as const cast on the array to preserve the tuple type.

ts
useHydrateAtoms([
  [countAtom, 42],
  [frameworkAtom, 'Next.js'],
] as const)

Or you may need to use a Map when passing the atom value to useHydrateAtoms. You can find a working example in the Initializing State on Render docs.

Demo

<Stackblitz id="stackblitz-starters-b7cvxi" file="pages%2Findex.tsx" />

There's more examples in the Next.js section.