{"_id":"jotai-ssr","_rev":"4-0184ca172513ae176a15b692478bf9e4","name":"jotai-ssr","dist-tags":{"latest":"0.2.0"},"versions":{"0.0.0":{"name":"jotai-ssr","version":"0.0.0","_id":"jotai-ssr@0.0.0","maintainers":[{"name":"daishi","email":"daishi@axlight.com"}],"dist":{"shasum":"e5bcca5e66ce85b768ec0db8aa6675eabe11d2eb","tarball":"https://registry.npmjs.org/jotai-ssr/-/jotai-ssr-0.0.0.tgz","fileCount":1,"integrity":"sha512-+Fe7cAVYt8/CO4P07qMEB/KIiJqmIxYfVkhrlvbCyAlpN/s/YzW4q2A5Ui30yQxoqUl8B9/rEeYgxoWHlqxguw==","signatures":[{"sig":"MEUCIBzZmdMAyieVRUMRYuEGH3IyZdp5bruOgZ8sCTgMuQIIAiEA291ivfIm7MCLh7bUW+8sx5gHbYIOXkO1+s3ToltLzrk=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":48},"_npmUser":{"name":"daishi","email":"daishi@axlight.com"},"_npmVersion":"9.6.7","directories":{},"_nodeVersion":"18.17.0","_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/jotai-ssr_0.0.0_1723433575193_0.07546503792037473","host":"s3://npm-registry-packages"}},"0.1.0":{"name":"jotai-ssr","version":"0.1.0","keywords":["jotai","react","ssr","server","hydrate"],"author":{"name":"Daisuke Akazawa"},"license":"MIT","_id":"jotai-ssr@0.1.0","maintainers":[{"name":"daishi","email":"daishi@axlight.com"},{"name":"akkadaska","email":"akkadaska@gmail.com"}],"homepage":"https://github.com/jotaijs/jotai-ssr#readme","bugs":{"url":"https://github.com/jotaijs/jotai-ssr/issues"},"dist":{"shasum":"1378cee3b6aeb895df67b1429e1497b509f70180","tarball":"https://registry.npmjs.org/jotai-ssr/-/jotai-ssr-0.1.0.tgz","fileCount":20,"integrity":"sha512-ZLeJ8vLhEgjKyDEJR7PpDlO267yOl80Nz/1ZkBmw6yrTkQRMLi5UDpNHbT+PZkKKGMEhFMqW0sPxgaMfEpq2Pg==","signatures":[{"sig":"MEQCICkTdmzeVsxmBV24gqH02A2qtX3qqFzL491qJ0sZqCgqAiA+Z0q98zVlsxMdUvCf4DPG0/obasAOAGv9YRlKcs/Vyg==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":18323},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","source":"./src/index.ts","exports":{".":{"default":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"require":{"types":"./dist/cjs/index.d.ts","default":"./dist/cjs/index.js"}},"./package.json":"./package.json"},"gitHead":"318bb6c241fb79cfec874851978ed32d28bb711f","scripts":{"test":"pnpm run '/^test:.*/'","compile":"rm -rf dist && pnpm run '/^compile:.*/'","test:lint":"eslint .","test:types":"tsc -p . --noEmit","compile:cjs":"tsc -p tsconfig.cjs.json && echo '{\"type\":\"commonjs\"}' > dist/cjs/package.json","compile:esm":"tsc -p tsconfig.esm.json"},"_npmUser":{"name":"daishi","email":"daishi@axlight.com"},"repository":{"url":"git+https://github.com/jotaijs/jotai-ssr.git","type":"git"},"_npmVersion":"10.8.1","description":"Jotai utilities for server-side rendering (SSR)","directories":{},"sideEffects":false,"_nodeVersion":"20.16.0","_hasShrinkwrap":false,"packageManager":"pnpm@9.2.0","devDependencies":{"jotai":"^2.9.2","react":"^18.3.1","eslint":"^9.9.0","prettier":"^3.3.3","typescript":"^5.5.4","@types/node":"^22.2.0","@types/react":"^18.3.3","@eslint/compat":"^1.1.1","@types/eslint__js":"^8.42.3","typescript-eslint":"^8.0.1","eslint-plugin-react":"^7.35.0","eslint-plugin-import":"^2.29.1","eslint-config-prettier":"^9.1.0","eslint-plugin-jsx-a11y":"^6.9.0","eslint-plugin-prettier":"^5.2.1","eslint-plugin-react-hooks":"^4.6.2","@types/eslint-plugin-jsx-a11y":"^6.9.0","eslint-import-resolver-typescript":"^3.6.1"},"peerDependencies":{"jotai":">=2.0.0","react":">=18.0.0"},"_npmOperationalInternal":{"tmp":"tmp/jotai-ssr_0.1.0_1723467422925_0.10363270121285328","host":"s3://npm-registry-packages"}},"0.1.1":{"name":"jotai-ssr","version":"0.1.1","keywords":["jotai","react","ssr","server","hydrate"],"author":{"name":"Daisuke Akazawa"},"license":"MIT","_id":"jotai-ssr@0.1.1","maintainers":[{"name":"daishi","email":"daishi@axlight.com"},{"name":"akkadaska","email":"akkadaska@gmail.com"}],"homepage":"https://github.com/jotaijs/jotai-ssr#readme","bugs":{"url":"https://github.com/jotaijs/jotai-ssr/issues"},"dist":{"shasum":"34000cf01d0a2ff8d38b589a8285f2d4dc970e03","tarball":"https://registry.npmjs.org/jotai-ssr/-/jotai-ssr-0.1.1.tgz","fileCount":20,"integrity":"sha512-kPq+lQzY+TcnAomGADMswgT7sjJGa0qbO+FbHykktR1aL97yCKpXhh43qshrBvpEJtbTtZ1CoKkr1QLz1SwmKA==","signatures":[{"sig":"MEUCIHkJcYj2YyTgJOPKHMC57ZbXztPTJPEPvGu2rC3fVUQxAiEA60NRC0dUaaMiaUjdUWl1Bj07lUG6wyI/t3jp61tAAMY=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":18724},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","source":"./src/index.ts","exports":{".":{"default":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"require":{"types":"./dist/cjs/index.d.ts","default":"./dist/cjs/index.js"}},"./package.json":"./package.json"},"gitHead":"52ebf11f87081a3b8356b7bc702a32cfa4e22cde","scripts":{"test":"pnpm run '/^test:.*/'","compile":"rm -rf dist && pnpm run '/^compile:.*/'","test:lint":"eslint .","test:types":"tsc -p . --noEmit","compile:cjs":"tsc -p tsconfig.cjs.json && echo '{\"type\":\"commonjs\"}' > dist/cjs/package.json","compile:esm":"tsc -p tsconfig.esm.json"},"_npmUser":{"name":"daishi","email":"daishi@axlight.com"},"repository":{"url":"git+https://github.com/jotaijs/jotai-ssr.git","type":"git"},"_npmVersion":"10.8.1","description":"Jotai utilities for server-side rendering (SSR)","directories":{},"sideEffects":false,"_nodeVersion":"20.16.0","_hasShrinkwrap":false,"packageManager":"pnpm@9.2.0","devDependencies":{"jotai":"^2.9.2","react":"^18.3.1","eslint":"^9.9.0","prettier":"^3.3.3","typescript":"^5.5.4","@types/node":"^22.2.0","@types/react":"^18.3.3","@eslint/compat":"^1.1.1","@types/eslint__js":"^8.42.3","typescript-eslint":"^8.0.1","eslint-plugin-react":"^7.35.0","eslint-plugin-import":"^2.29.1","eslint-config-prettier":"^9.1.0","eslint-plugin-jsx-a11y":"^6.9.0","eslint-plugin-prettier":"^5.2.1","eslint-plugin-react-hooks":"^4.6.2","@types/eslint-plugin-jsx-a11y":"^6.9.0","eslint-import-resolver-typescript":"^3.6.1"},"peerDependencies":{"jotai":">=2.0.0","react":">=18.0.0"},"_npmOperationalInternal":{"tmp":"tmp/jotai-ssr_0.1.1_1723549547908_0.6101817409657508","host":"s3://npm-registry-packages"}},"0.2.0":{"name":"jotai-ssr","description":"Jotai utilities for server-side rendering (SSR)","version":"0.2.0","type":"module","author":{"name":"Daisuke Akazawa"},"repository":{"type":"git","url":"git+https://github.com/jotaijs/jotai-ssr.git"},"source":"./src/index.ts","main":"./dist/index.js","types":"./dist/index.d.ts","exports":{"./package.json":"./package.json",".":{"require":{"types":"./dist/cjs/index.d.ts","default":"./dist/cjs/index.js"},"default":{"types":"./dist/index.d.ts","default":"./dist/index.js"}}},"sideEffects":false,"packageManager":"pnpm@9.15.2","scripts":{"compile":"rm -rf dist && pnpm run '/^compile:.*/'","compile:esm":"tsc -p tsconfig.esm.json","compile:cjs":"tsc -p tsconfig.cjs.json && echo '{\"type\":\"commonjs\"}' > dist/cjs/package.json","test":"pnpm run '/^test:.*/'","test:lint":"eslint .","test:types":"tsc -p . --noEmit"},"keywords":["jotai","react","ssr","server","hydrate"],"license":"MIT","peerDependencies":{"jotai":">=2.0.0","react":">=18.0.0"},"devDependencies":{"@eslint/compat":"^1.2.4","@types/eslint-plugin-jsx-a11y":"^6.10.0","@types/eslint__js":"^8.42.3","@types/node":"^22.10.5","@types/react":"^19.0.2","eslint":"^9.17.0","eslint-config-prettier":"^9.1.0","eslint-import-resolver-typescript":"^3.7.0","eslint-plugin-import":"^2.31.0","eslint-plugin-jsx-a11y":"^6.10.2","eslint-plugin-prettier":"^5.2.1","eslint-plugin-react":"^7.37.3","eslint-plugin-react-hooks":"^5.1.0","jotai":"^2.11.0","prettier":"^3.4.2","react":"^19.0.0","typescript":"^5.7.2","typescript-eslint":"^8.19.0"},"_id":"jotai-ssr@0.2.0","gitHead":"655cdf2f0bc66843ba15bd5e61fb7165c4fa81f0","bugs":{"url":"https://github.com/jotaijs/jotai-ssr/issues"},"homepage":"https://github.com/jotaijs/jotai-ssr#readme","_nodeVersion":"20.18.1","_npmVersion":"10.8.2","dist":{"integrity":"sha512-WZAisk8i4K2ITykAkyOR2EP3j2W4QGaeJrez+udcg5uELLzTEtGvqzo5/rgd7CFUCM4ONaqBJrmLuLWBiseI8g==","shasum":"e0e6cd54ef6097ac82931d17f7e7e6d8acbabed3","tarball":"https://registry.npmjs.org/jotai-ssr/-/jotai-ssr-0.2.0.tgz","fileCount":24,"unpackedSize":24984,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCOWjgfN3a6NW8GODQWJo5Lidex8mbf+wTVver/Lt3UnQIhAJklgS8vqm7D4T+V4AdwA688Qy5lJ9QUlyZYdSX5814d"}]},"_npmUser":{"name":"daishi","email":"daishi@axlight.com"},"directories":{},"maintainers":[{"name":"daishi","email":"daishi@axlight.com"},{"name":"akkadaska","email":"akkadaska@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/jotai-ssr_0.2.0_1735981839359_0.2821039285404432"},"_hasShrinkwrap":false}},"time":{"created":"2024-08-12T03:32:55.192Z","modified":"2025-01-04T09:10:39.731Z","0.0.0":"2024-08-12T03:32:55.306Z","0.1.0":"2024-08-12T12:57:03.080Z","0.1.1":"2024-08-13T11:45:48.063Z","0.2.0":"2025-01-04T09:10:39.557Z"},"bugs":{"url":"https://github.com/jotaijs/jotai-ssr/issues"},"author":{"name":"Daisuke Akazawa"},"license":"MIT","homepage":"https://github.com/jotaijs/jotai-ssr#readme","keywords":["jotai","react","ssr","server","hydrate"],"repository":{"type":"git","url":"git+https://github.com/jotaijs/jotai-ssr.git"},"description":"Jotai utilities for server-side rendering (SSR)","maintainers":[{"name":"daishi","email":"daishi@axlight.com"},{"name":"akkadaska","email":"akkadaska@gmail.com"}],"readme":"# jotai-ssr\n\n**jotai-ssr** is a utility library for [Jotai](https://jotai.org/) to facilitate server-side rendering (SSR). It provides helpers for:\n\n- **Hydrating** atom values from server to client (and optionally re-hydrating).\n- Handling SSR scenarios, including **React Server Components** and soft navigations in frameworks like Next.js, Remix, and Waku.\n\nThis library extends or wraps the existing Jotai SSR utilities to provide a more seamless integration with modern SSR setups.\n\n---\n\n## Table of Contents\n\n1. [Installation](#installation)  \n2. [Creating a Safe Store for Each Request](#creating-a-safe-store-for-each-request)\n3. [Hydration](#hydration)  \n   1. [What is Hydration?](#what-is-hydration)  \n   2. [How to Hydrate an Atom](#how-to-hydrate-an-atom)  \n   3. [`HydrationBoundary`](#hydrationboundary)  \n4. [Streaming Hydration with Async Atoms](#streaming-hydration-with-async-atoms)\n5. [Important Notes on Hydration Logic](#important-notes-on-hydration-logic)  \n6. [Soft Navigation in SSR Frameworks](#soft-navigation-in-ssr-frameworks)  \n7. [Re-Hydration](#re-hydration)  \n\n---\n\n## Installation\n\n```bash\nnpm install jotai-ssr\n# or\nyarn add jotai-ssr\n# or\npnpm add jotai-ssr\n```\n\n---\n\n## Creating a Safe Store for Each Request\n\nWhen using Jotai in an SSR environment, **you must ensure each request has its own store**. Relying on a shared, global store (e.g. `defaultStore`) across requests can lead to data leakage between different users.\n\nTo create an isolated store per request, you should use `Provider` for each layout or page that uses Jotai like so:\n\n```tsx\nimport { Provider } from 'jotai';\n\nconst Page = () => {\n  return (\n    <Provider>{/* Your content */}</Provider>\n  );\n};\n```\n\nIf you need to pass a custom store to the `Provider`, you can do so in one of the following ways:\n\n1. **Using useState**\n\n   ```tsx\n   'use client';\n\n   import { createStore, Provider } from 'jotai';\n   import { useState } from 'react';\n\n   const Page = () => {\n     const [store] = useState(() => createStore());\n     return <Provider store={store}>{/* your content */}</Provider>;\n   };\n   ```\n\n2. **Using useRef**\n\n   ```tsx\n   'use client';\n\n   import { createStore, Provider } from 'jotai';\n   import { useRef } from 'react';\n\n   const Page = () => {\n     const storeRef = useRef(undefined);\n     if (!storeRef.current) {\n       storeRef.current = createStore();\n     }\n     return <Provider store={storeRef.current}>{/* your content */}</Provider>;\n   };\n   ```\n\nBoth approaches ensure a new store instance is created for each request, preventing data from leaking between different users.\n\n---\n\n## Hydration\n\nWhen data is fetched on the server and passed to the client, you may want to initialize Jotai atoms with those server-side values. This process is called **hydration**.\n\n### What is Hydration?\n\nHydration sets up atoms with initial values so that:\n\n- The server-rendered HTML uses the correct initial state.\n- Once the client side finishes React hydration, the atom is already in the correct state without causing extra re-renders.\n\n### How to Hydrate an Atom\n\nWhen dealing with SSR, you often have data fetched on the server that needs to be passed to your components and stored in Jotai atoms. To accomplish this, **jotai-ssr** provides a `useHydrateAtoms` hook similar to the one in Jotai’s [`jotai/utils`](https://jotai.org/docs/utilities/ssr#usage), with a few small differences:\n\n1. **No** `dangerouslyForceHydrate` **option**  \n2. Exported from **`jotai-ssr`** rather than `jotai/utils`  \n\nApart from these differences, the usage is nearly the same as the official Jotai version. This means you can hydrate your atoms with data like so:\n\n```tsx\n'use client'; // If you're using React Server Components (RSC), ensure the file is a Client Component\n\nimport { atom, useAtom } from 'jotai';\nimport { useHydrateAtoms } from 'jotai-ssr';\n\n// Example atom\nexport const countAtom = atom(0);\n\ninterface PageProps {\n  countFromServer: number;\n}\n\nexport function Page({ countFromServer }: PageProps) {\n  // 1. Hydrate the atom with a value fetched on the server\n  useHydrateAtoms([[countAtom, countFromServer]]);\n  \n  // 2. Now you can safely use the atom in your component\n  const [count] = useAtom(countAtom);\n\n  return <div>Count: {count}</div>;\n}\n```\n\nHere’s what you need to know:\n\n1. **Client-Side Usage**:  \n   Despite the term “SSR” in its name, `useHydrateAtoms` must be called in client code (i.e., a component with `'use client'` at the top if you’re using React Server Components).\n\n2. **Optional `store` Parameter**:  \n   Just like the Jotai version, you can target a specific store by providing the `store` option. For example:\n   ```tsx\n   import { createStore } from 'jotai';\n\n   const myStore = createStore();\n   useHydrateAtoms([[countAtom, 42]], { store: myStore });\n   ```\n\n3. **No `dangerouslyForceHydrate`**:  \n   Unlike the original Jotai hook, the **jotai-ssr** version does **not** provide a `dangerouslyForceHydrate` option. If you need more advanced re-hydration behavior, see [Re-Hydration](#re-hydration).\n\n> **Tip:** Hydrating an atom **does not** cause additional re-renders if you do it **before** using the atom in your component. Make sure to call `useHydrateAtoms` at the top level of your component (or inside its parent) so that the initial render already has the right atom values.\n\n### `HydrationBoundary`\n\nFor React Server Components (RSC) and for a clearer boundary-based approach, **jotai-ssr** provides a `HydrationBoundary` component:\n\n```tsx\nimport { HydrationBoundary } from 'jotai-ssr';\nimport { countAtom } from './atoms'; // \"use client\" inside this file\n\nconst ServerComponent = async () => {\n  const countFromServer = await fetchCount();\n  return (\n    <HydrationBoundary hydrateAtoms={[[countAtom, countFromServer]]}>\n      {/* Components that consume countAtom */}\n    </HydrationBoundary>\n  );\n};\n```\n\nYou can pass an optional `options` prop, such as `{ store: myStore }`, if you want to hydrate into a specific store.\n\n> **Note**: `HydrationBoundary` can be used in both Client and Server Components. However, when using it in a Server Component, the atom definitions must be marked with `'use client'`. Also, any value you pass for hydration **must be serializable**. This is because `HydrationBoundary` itself is a React Client Component.\n\n---\n\n## Streaming Hydration with Async Atoms\n\nSome SSR frameworks (like Next.js) support **streaming responses** so that part of your UI can render before all data is loaded. With Jotai, you can stream data from the server into **async atoms**. This allows your components to start rendering in a suspended state, then reveal when the data arrives. Here’s how you can do it with **jotai-ssr**:\n\n### Defining an Async Atom\n\nFirst, define an atom that holds a promise:\n\n```tsx\n'use client';\n\nimport { atom, useAtomValue } from 'jotai';\n\n// Define an async atom that resolves to a number.\nexport const countAtom = atom<Promise<number>>();\n\nexport const CountComponent = () => {\n  // Jotai will automatically suspend here until the promise resolves\n  const count = useAtomValue(countAtom);\n  return <div>{count}</div>;\n};\n```\n\n> **Note**: Because this is an async atom, **any** component reading it will suspend by default, so you must wrap it with `<Suspense>`.\n\n### Streaming Hydration in the Server/Edge Environment\n\nNext, in your server-side or edge code, you can fetch the data and hydrate the async atom with a **promise**:\n\n```tsx\nimport { HydrationBoundary } from 'jotai-ssr';\nimport { Suspense } from 'react';\nimport { countAtom, CountComponent } from './client';\n\nexport const StreamingHydration = () => {\n  // Suppose this fetchCount function returns a Promise<number>\n  const countPromise = fetchCount();\n\n  return (\n    <HydrationBoundary hydrateAtoms={[[countAtom, countPromise]]}>\n      <Suspense fallback={<div>loading...</div>}>\n        <CountComponent />\n      </Suspense>\n    </HydrationBoundary>\n  );\n};\n```\n\n1. **Fetch or stream data** (e.g., `fetchCount()`) on the server.  \n2. **Hydrate** the async atom by passing `[countAtom, countPromise]` to `HydrationBoundary`.  \n3. **Wrap** your async-consuming components (`<CountComponent />`) with a `<Suspense>` boundary to handle the loading state.\n\nThis setup ensures that:\n\n- The async atom suspends until the promise resolves.  \n- The hydrated value is set **immediately** in the store, allowing the client to continue with the same promise.  \n- React’s Suspense boundary displays a fallback (`loading...`) until the atom’s promise settles.\n\nThis pattern allows you to combine the power of **async atoms** with server-side streaming, letting Jotai manage data states in a way that feels natural within React’s **Suspense** model.\n\n---\n\n## Important Notes on Hydration Logic\n\n### 1. Hydrate Before Using the Atom\n\nHydration sets atom **initial values**. Thus, you should not use the atom in a component **before** calling `useHydrateAtoms`. Instead, do something like this:\n\n**Correct usage**:\n```tsx\nconst Component = ({ countFromServer }) => {\n  useHydrateAtoms([[countAtom, countFromServer]]);\n  const [count] = useAtom(countAtom);\n  return <div>{count}</div>;\n};\n```\nor\n```tsx\nconst Component = async ({ countFromServer }) => {\n  return (\n    <HydrationBoundary hydrateAtoms={[[countAtom, countFromServer]]}>\n      <CountComponent />\n    </HydrationBoundary>\n  );\n};\n```\n\n**Incorrect usage** (atom used before hydration):\n```tsx\n// Don't do this\nconst Component = ({ countFromServer }) => {\n  const [count] = useAtom(countAtom);\n  useHydrateAtoms([[countAtom, countFromServer]]);\n  return <div>{count}</div>;\n};\n```\nor\n```tsx\n// Don't do this\nconst Component = async ({ countFromServer }) => {\n  const [count] = useAtom(countAtom);\n  return (\n    <HydrationBoundary hydrateAtoms={[[countAtom, countFromServer]]}>\n      <div>{count}</div>\n    </HydrationBoundary>\n  );\n};\n```\n\n### 2. Do Not Hydrate the Same Atom in Multiple Places Within the Same Provider\n\nA single Jotai `Provider` shares atom states across its entire tree. Hydrating the same atom in multiple child components can lead to unexpected re-renders. Instead, hydrate each atom once. If you really need separate hydration for the same atom, place them in **different** providers or use [jotai-scope](https://jotai.org/docs/extensions/scope#jotai-scope) to scope them.\n\n### 3. Hydration Only Occurs on Initial Mount\n\nHydration sets the atom value **only** on the first render (just like a `useState` initial value in React). Subsequent props changes do **not** cause re-hydration. If a component unmounts and remounts, it will re-hydrate at that time.\n\n---\n\n## Soft Navigation in SSR Frameworks\n\nIn frameworks like **Next.js**, **Remix**, and **Waku**, soft navigation means some part of your layout or component tree does **not** unmount between page transitions. For instance:\n\n- **Next.js App Router**: `layout.jsx` might persist across routes.\n- **Remix**: `root.jsx` can persist across routes.\n- **Waku**: `layout.jsx` can persist across pages.\n\n> **Note**: A similar example is when the path includes a slug, and navigation occurs between pages with different slugs. In such cases, particularly in Remix and Waku, the page component itself tends to persist.\n\nWhen using soft navigation:\n\n- If your Jotai `Provider` is in a **layout** that persists, its store does **not** get recreated on page transitions. Data from previous pages is carried over.\n- If your Jotai `Provider` is placed in a **page** component, it will be recreated on each navigation, effectively isolating state per page.\n\nTherefore, be mindful where you place the `Provider` or the hydration logic. If a persistent layout hydrates the same atom across different routes, you could trigger unwanted re-renders on route changes. Generally, **avoid hydrating atoms in a page** if the `Provider` is in a layout that persists.\n\n---\n\n## Re-Hydration\n\nBy default, **hydration happens only once**: on the initial mount. Even if you pass new values to `useHydrateAtoms` or `HydrationBoundary` after that, the atom values remain as they were set the first time.\n\nHowever, if you need to **re-hydrate** (e.g., to sync with the latest server data after a route refresh), you can enable re-hydration:\n\n- With `useHydrateAtoms`:\n\n  ```tsx\n  import { useHydrateAtoms } from 'jotai-ssr';\n\n  const Component = ({ countFromServer }) => {\n    useHydrateAtoms([[countAtom, countFromServer]], { enableReHydrate: true });\n    const [count] = useAtom(countAtom);\n    return <div>{count}</div>;\n  };\n  ```\n\n- With `HydrationBoundary`:\n\n  ```tsx\n  const ServerComponent = async () => {\n    const countFromServer = await fetchCount();\n    return (\n      <HydrationBoundary\n        hydrateAtoms={[[countAtom, countFromServer]]}\n        options={{ enableReHydrate: true }}\n      >\n        <CountComponent />\n      </HydrationBoundary>\n    );\n  };\n  ```\n\nWhen `enableReHydrate` is `true`, the component compares the new hydration values (via `Object.is`) and re-hydrates if they differ.\n\n### Route Refresh Considerations\n\nIn Next.js App Router, calling `router.refresh()` or `revalidatePath()` triggers server code to re-fetch data, but the same client component instance persists. Normally, `useState` or Jotai hydration wouldn’t reset values. By turning on re-hydration, you can ensure your atoms get updated with the newest fetched data.\n\nThe same principle applies in Remix or Waku if the layout is partially reused during a slug-based soft navigation.\n\n---\n\n## License\n\nMIT License. See [LICENSE](./LICENSE) for details.\n\n---\n\n## Feedback\nThis is a new package and we would love to hear your feedback.\nRelated discussion: https://github.com/pmndrs/jotai/discussions/2692\n\n---\n","readmeFilename":"README.md"}