{"id":18552377,"url":"https://github.com/traviswimer/react-hydration-provider","last_synced_at":"2025-04-09T22:31:52.121Z","repository":{"id":57714356,"uuid":"514239273","full_name":"traviswimer/react-hydration-provider","owner":"traviswimer","description":"react-hydration-provider makes it easy to control what your app renders before and after app hydration.","archived":false,"fork":false,"pushed_at":"2023-11-15T14:36:15.000Z","size":193,"stargazers_count":45,"open_issues_count":0,"forks_count":2,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-03-24T13:11:24.754Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/traviswimer.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-07-15T11:09:19.000Z","updated_at":"2025-02-09T08:47:24.000Z","dependencies_parsed_at":"2024-06-18T21:28:22.517Z","dependency_job_id":"539e2ec0-8f30-4d3d-bb87-80cc903b4749","html_url":"https://github.com/traviswimer/react-hydration-provider","commit_stats":{"total_commits":18,"total_committers":3,"mean_commits":6.0,"dds":"0.11111111111111116","last_synced_commit":"69b6aec8725f9ad6db0b2a6c6f280c2a300a1f18"},"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/traviswimer%2Freact-hydration-provider","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/traviswimer%2Freact-hydration-provider/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/traviswimer%2Freact-hydration-provider/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/traviswimer%2Freact-hydration-provider/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/traviswimer","download_url":"https://codeload.github.com/traviswimer/react-hydration-provider/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247965320,"owners_count":21025361,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-06T21:14:02.346Z","updated_at":"2025-04-09T22:31:51.679Z","avatar_url":"https://github.com/traviswimer.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n  \u003cimg alt=\"react-hydration-provider\" src=\"./react-hydration-provider-logo.png\" width=\"400\"\u003e\n\u003c/p\u003e\n\n\u003e `react-hydration-provider` makes it easy to control what your app renders before and after app hydration.\n\u003e\n\u003e This makes it simple to avoid hydration errors and other problems related to Server-side Rendering (SSR), Static Site Generation (SSG), Deferred Static Generation (DSG), etc.\n\n- [Learn about the problems this solves.](#problem-explanation)\n- [View Examples](#examples)\n- [Read the API reference](#api)\n- \u003ca href=\"https://traviswimer.com/blog/easily-fix-react-hydration-errors\" target=\"_blank\" title=\"Easily Fix React Hydration Errors\"\u003eBlog post about React hydration issues\u003c/a\u003e\n\n## Getting Started\n\n### Install\n\n**Yarn:**\n\n```shell\nyarn add react-hydration-provider\n```\n\n**NPM:**\n\n```shell\nnpm install react-hydration-provider\n```\n\n### importing the package\n\n**ES import**\n\n```javascript\nimport {\n\tHydrationContext,\n\tHydrationProvider,\n\tuseHydrated,\n\tServer,\n\tClient,\n\tcreateHydration,\n\tuseComponentHydrated,\n} from \"react-hydration-provider\";\n```\n\n**CommonJS require()**\n\n```javascript\nconst {\n\tHydrationContext,\n\tHydrationProvider,\n\tuseHydrated,\n\tServer,\n\tClient,\n\tcreateHydration,\n\tuseComponentHydrated,\n} = require(\"react-hydration-provider\");\n```\n\n### Usage with Server Components\n\n_Requires `react-hydration-provider` version 2.1.0 or later_\n\nIf you are using [React Server Components](https://react.dev/blog/2023/03/22/react-labs-what-we-have-been-working-on-march-2023#react-server-components), you should be able to use `HydrationProvider` and it's corresponding hooks/components without any changes.\n\nIf you are using the standalone `useComponentHydrated` hook, you will need to include the [`\"use client\";`](https://react.dev/reference/react/use-client) directive in any component that uses it.\n\n\u003ch3 id=\"examples\"\u003eUsage examples\u003c/h3\u003e\n\n**Basic Example**\n\n```javascript\nimport { HydrationProvider, Server, Client } from \"react-hydration-provider\";\n\nfunction App() {\n\treturn (\n\t\t// HydrationProvider should usually be placed at a high level in your app.\n\t\t\u003cHydrationProvider\u003e\n\t\t\t\u003cmain\u003e\n\t\t\t\t\u003cServer\u003e\n\t\t\t\t\t\u003cp\u003e\n\t\t\t\t\t\tThis will be rendered during html generation (SSR, SSG, etc) and the\n\t\t\t\t\t\tinitial app hydration. It should always have a reliable value that\n\t\t\t\t\t\twill render the same in both a server and client environment.\n\t\t\t\t\t\u003c/p\u003e\n\t\t\t\t\u003c/Server\u003e\n\t\t\t\t\u003cClient\u003e\n\t\t\t\t\t\u003cp\u003eThis will be rendered after initial app hydration.\u003c/p\u003e\n\t\t\t\t\t\u003cp\u003e\n\t\t\t\t\t\tIt can safely contain dynamic content, like this: {Math.random()}\n\t\t\t\t\t\u003c/p\u003e\n\t\t\t\t\u003c/Client\u003e\n\t\t\t\t\u003cp\u003eThis will always be rendered.\u003c/p\u003e\n\t\t\t\u003c/main\u003e\n\t\t\u003c/HydrationProvider\u003e\n\t);\n}\n```\n\n**Only render on client**\n\n```javascript\nimport { HydrationProvider, Server, Client } from \"react-hydration-provider\";\n\nfunction App() {\n\treturn (\n\t\t\u003cHydrationProvider\u003e\n\t\t\t\u003cmain\u003e\n\t\t\t\t\u003cClient\u003e\n\t\t\t\t\t\u003cp\u003e\n\t\t\t\t\t\tNothing will be rendered to the user until the React app has\n\t\t\t\t\t\tinitialized and hydrated.\n\t\t\t\t\t\u003c/p\u003e\n\t\t\t\t\u003c/Client\u003e\n\t\t\t\u003c/main\u003e\n\t\t\u003c/HydrationProvider\u003e\n\t);\n}\n```\n\n**Manually checking hydration state**\n\n```javascript\nimport { HydrationProvider, useHydrated } from \"react-hydration-provider\";\n\nfunction MyComponent() {\n\t// useHydrated() is the same hook used by the \u003cClient\u003e and \u003cServer\u003e components.\n\t// If \u003cClient\u003e and \u003cServer\u003e don't meet your needs, this can be used instead.\n\tconst hydrated = useHydrated();\n\treturn hydrated ? \u003cp\u003eClient render\u003c/p\u003e : \u003cp\u003eServer render\u003c/p\u003e;\n}\n\nfunction App() {\n\treturn (\n\t\t\u003cHydrationProvider\u003e\n\t\t\t\u003cmain\u003e\n\t\t\t\t\u003cMyComponent /\u003e\n\t\t\t\u003c/main\u003e\n\t\t\u003c/HydrationProvider\u003e\n\t);\n}\n```\n\n**Skip the Provider**\n\n`useComponentHydrated()` will cause a component to independently determine if the app is hydrated and may be less efficient.\n\nUsually you will want to use `\u003cHydrationProvider` along with `useHydrated()` or the `\u003cServer\u003e` and `\u003cClient\u003e` components. Using the provider allows the hydration check to only be performed once for your entire app.\n\n[Read more about why you should use `useHydrated()` instead.](#hydration-rerenders-explanation)\n\n```javascript\nimport { useComponentHydrated } from \"react-hydration-provider\";\n\nfunction MyComponent() {\n\tconst hydrated = useComponentHydrated();\n\treturn hydrated ? \u003cp\u003eClient render\u003c/p\u003e : \u003cp\u003eServer render\u003c/p\u003e;\n}\n\nfunction App() {\n\treturn (\n\t\t\u003cmain\u003e\n\t\t\t\u003cMyComponent /\u003e\n\t\t\u003c/main\u003e\n\t);\n}\n```\n\n\u003ch2 id=\"api\"\u003eAPI Reference\u003c/h2\u003e\n\n### `\u003cHydrationProvider\u003e`\n\nA Context Provider that allows child components to determine if the app has been hydrated.\n\nThis should generally be used near the highest level of your app.\n\n_The only prop accepted is `children`_\n\n### `\u003cServer\u003e`\n\nComponent to wrap the content you want to render when HTML is generated on a server or your local machine (SSR, SSG, DSG, etc). This content will also be rendered during the first render of your app to ensure your app matches the HTML during hydration.\n\n**IMPORTANT: Ensure child components of `\u003cServer\u003e` are always predictable. It should always render the same. If not, you may still see hydration errors.**\n\n### `\u003cClient\u003e`\n\nComponent to wrap the content you want to render after your React app has hydrated. It should never be rendered on the server-side.\n\nInside this component child components do not need to be reliable. It can render differently every time and there will be no hydration issues.\n\n### `useHydrated()`\n\n**React hook function**\n\nReturns `true` if app is hydrated. Returns `false` if it has not yet been hydrated.\n\n### `HydrationContext`\n\nThe React `Context` used by `HydrationProvider`.\n\nYou probably don't need to use this, but it is available in case there is an edge-case that requires it.\n\n### `useComponentHydrated()`\n\n**React hook function**\n\nYou should usually use `useHydrated()` instead.\n\nIt works exactly the same as `useHydrated()`, except the component using it will independently perform the hydration check each time it is mounted. This may [lead to inefficiencies](#hydration-rerenders-explanation).\n\nThis hook can be used completely independently. It does not require the use of a `HydrationProvider`.\n\n### `createHydration()`\n\n**Factory function to allow the use of multiple providers**\n\nThis function returns the same API as documented here (with the exception of `useComponentHydrated()` and `createHydration`):\n\n- HydrationContext\n- HydrationProvider\n- Server\n- Client\n- useHydrated()\n\nThis should only be necessary in complex scenarios where multiple Providers/Contexts are necessary.\n\n_Example:_\n\n```javascript\nconst { HydrationContext, HydrationProvider, useHydrated, Server, Client } =\n\tcreateHydration();\n```\n\n\u003ch2 id=\"problem-explanation\"\u003eWhat problems does this solve?\u003c/h2\u003e\n\n\u003ch3 id=\"hydration-errors-explanation\"\u003eHydration Errors from client/server mismatch\u003c/h3\u003e\n\nServer-Side Rendering (SSR) and other pre-rendering methods require your client-side React app to use a process called \"hydration\" to seamlessly transition the HTML received from the server into an interactive Single-Page App (SPA).\n\nFor this to work correctly, the HTML from the server needs to **exactly** match what is generated by your React app or you will see errors/warnings:\n\n- `Warning: Text content did not match. Server: \"Pre-rendered server content\" Client: \"Client app content\" at div.`\n- `Warning: An error occurred during hydration. The server HTML was replaced with client content in div.`\n- `Text content does not match server-rendered HTML.`\n- `Hydration failed because the initial UI does not match what was rendered on the server.`\n- `There was an error while hydrating. Because the error happened outside of a Suspense boundary, the entire root will switch to client rendering.`\n\nThis is generally a result of your React app using dynamic content. For example, you might be using dates formatted to the current user's locale or you might be retrieving data from `localStorage`.\n\nIn these cases, your app requires data that is only available on the user's machine. Obviously the server (or your local machine) has no way of knowing what this data will be.\n\n`react-hydration-provider` solves this using the `\u003cServer\u003e` and `\u003cClient\u003e` components. Putting all your dynamic content (Dates, localStorage, etc.) inside a `\u003cClient\u003e` ensures that it is not included during \"hydration\". If you want some content to be displayed only before the app has hydrated, you simply put it inside a `\u003cServer\u003e`. It is still possible to encounter mismatch errors from the content inside a `\u003cServer\u003e`. Ensure that it is always static/predictable on both the client and server.\n\n\u003ch3 id=\"hydration-rerenders-explanation\"\u003eOnly one re-render\u003c/h3\u003e\n\nAs the name implies, `react-hydration-provider` utilizes a React Context Provider (`HydrationProvider`) to store the hydration state of your React app.\n\nThe purpose of this is to only require the hydration check to run once at the highest level and then pass that down to `\u003cServer\u003e` and `\u003cClient\u003e` components.\n\nThe common way to check if an app is hydrated is to use `useEffect()` to delay certain code until after the first render. This is the technique used in `useComponentHydrated()`:\n\n```javascript\nexport function useComponentHydrated() {\n\t// Once useEffect() has been called, we know the app has been hydrated.\n\tconst [hydrated, setHydrated] = React.useState(false);\n\tReact.useEffect(() =\u003e {\n\t\tsetHydrated(true);\n\t}, []);\n\n\treturn hydrated;\n}\n```\n\nWhen you use this hook, it will trigger a re-render in the component that uses it when the value of `hydrated` changes.\n\nImagine you have a site with 2 pages, `page-a` and `page-b`. If a user directly navigates to the URL for `page-a`, your server will send them the HTML for `page-a`. Then your React app will hydrate and any components in `page-a` using `useComponentHydrated()` will re-render.\n\nAt this point everything is great, but now let's say the user clicks a link to navigate to `page-b`. Any components in `page-b` using `useComponentHydrated()` will render twice. This is completely unnecessary, as hydration mismatches are only a concern when the app first initializes.\n\nBy using a `\u003cHydrationProvider\u003e`, `\u003cServer\u003e`, and `\u003cClient\u003e`, `react-hydration-provider` is able to run this check only once when the React app first initializes, eliminating the need for components to constantly re-render.\n\nBasically, anything inside a `\u003cServer\u003e` will never be rendered if the app has already hydrated.\n\n### SEO with dynamic content\n\nOne of the benefits of pre-rendering your HTML is that it makes it easier for search engines to crawl your site, since it isn't dependent on your React app initializing.\n\nAs explained in the [previous section](#hydration-errors-explanation), dynamic content causes hydration errors. A common solution is to simply delay rendering this content until after hydration. That means the HTML file will not contain this content, eliminating the SEO benefits.\n\nIn these cases, you can use the `\u003cServer\u003e` component to specify static content that should be included in the HTML file, allowing search engines to see this content before your React app has initialized.\n\n### Displaying placeholders before app initialization\n\nThe `\u003cServer\u003e` component makes it simple to include placeholders like loading-spinners to improve your site's UX before the React app has initialized.\n\n## Project Links\n\n- [NPM](https://www.npmjs.com/package/react-hydration-provider)\n- [GitHub](https://github.com/traviswimer/react-hydration-provider)\n\n## Author\n\n#### Travis Wimer\n\n- \u003ca href=\"https://traviswimer.com/developer-portfolio\" title=\"React Native, React, NodeJS, UI/UX Developer\" target=\"_blank\"\u003eDeveloper Portfolio\u003c/a\u003e\n- \u003ca href=\"https://traviswimer.com/blog\" title=\"React Native, React, NodeJS, UI/UX Blog\" target=\"_blank\"\u003eBlog\u003c/a\u003e\n- \u003ca href=\"https://www.linkedin.com/in/traviswimer/\" title=\"Developer Resume\" target=\"_blank\"\u003eLinkedIn\u003c/a\u003e\n- \u003ca href=\"https://twitter.com/Travis_Wimer\" title=\"Travis Wimer | Software Developer\" target=\"_blank\"\u003eTwitter\u003c/a\u003e\n- \u003ca href=\"https://traviswimer.com/developer-portfolio/react-hydration-provider\" title=\"react-hydration-provider | Travis Wimer\" target=\"_blank\"\u003ereact-hydration-provider Portfolio Page\u003c/a\u003e\n\n## License\n\nMIT. Copyright © 2022 Travis Wimer\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftraviswimer%2Freact-hydration-provider","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftraviswimer%2Freact-hydration-provider","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftraviswimer%2Freact-hydration-provider/lists"}