{"id":16910572,"url":"https://github.com/estrattonbailey/react-hydrate","last_synced_at":"2025-03-22T10:31:49.818Z","repository":{"id":71080744,"uuid":"94815234","full_name":"estrattonbailey/react-hydrate","owner":"estrattonbailey","description":"Generic data fetching, caching, and SSR hydration pattern for React","archived":false,"fork":false,"pushed_at":"2017-08-22T00:11:11.000Z","size":501,"stargazers_count":31,"open_issues_count":2,"forks_count":1,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-03-15T23:15:46.637Z","etag":null,"topics":["async","react","react-ssr"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/estrattonbailey.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"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":"2017-06-19T19:52:05.000Z","updated_at":"2021-09-05T14:46:36.000Z","dependencies_parsed_at":"2023-03-24T14:35:14.917Z","dependency_job_id":null,"html_url":"https://github.com/estrattonbailey/react-hydrate","commit_stats":{"total_commits":34,"total_committers":1,"mean_commits":34.0,"dds":0.0,"last_synced_commit":"33801e5efafd56cf32df6cfd58ef3727a6cfb43f"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/estrattonbailey%2Freact-hydrate","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/estrattonbailey%2Freact-hydrate/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/estrattonbailey%2Freact-hydrate/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/estrattonbailey%2Freact-hydrate/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/estrattonbailey","download_url":"https://codeload.github.com/estrattonbailey/react-hydrate/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244201665,"owners_count":20415125,"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":["async","react","react-ssr"],"created_at":"2024-10-13T19:01:47.832Z","updated_at":"2025-03-22T10:31:49.417Z","avatar_url":"https://github.com/estrattonbailey.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# react-hydrate\nGeneric data fetching and SSR hydration pattern for React.\n\n[![js-standard-style](https://cdn.rawgit.com/feross/standard/master/badge.svg)](http://standardjs.com)\n\n## Features \u0026 Goals\n1. Co-locate data dependencies with your components\n2. Supports infinitely nested loaders\n3. Fetches requested data on the server and hydrates on the client for a fast startup\n4. Wraps components so users can easily define loading states for components\n5. Routing agnostic. **Works with `react-router` v4.**\n6. Lightweight **~1.9kb**\n\nRelated: [react-hydrate-link](https://github.com/estrattonbailey/react-hydrate-link) - prefetch data for your next route using react-router v4.\n\n## Usage\n### Defining components\n```javascript\n/**\n * Projects.js\n */\nimport api from 'my-api'\nimport { hydrate } from 'react-hydrate'\nimport Project from './Project.js'\n\nexport default hydrate(\n  /**\n   * dataLoader receives component props\n   * and any state already in the store\n   */\n  (props, state) =\u003e {\n    return api.fetchProjects().then(projects =\u003e {\n      return {\n        projects: projects\n      }\n    })\n  },\n  /**\n   * mapStateToProps receives the\n   * loaded data via `state` and any\n   * component props.\n   *\n   * You should return `false` here if \n   * the data needed is not yet availabe.\n   * If a falsy value is returned, it\n   * tells the library that the loader\n   * hasn't been run yet or hasn't\n   * yet resolved.\n   */\n  (state, props) =\u003e {\n    return state.projects ? {\n      projects: state.projects\n    } : false\n  }\n)(({ loading, data, ...inheritedProps }) =\u003e {\n  /**\n   * Component is always passed a loading\n   * prop that represents the status of their\n   * dataLoader function\n   */\n  return loading ? (\n    \u003cdiv\u003eLoading data...\u003c/div\u003e\n  ) : (\n    data.projects.map(project =\u003e \u003cProject {...project} key={project.slug}\u003e)\n  )\n})\n```\n\n```javascript\n/**\n * App.js\n */\nimport React from 'react'\nimport Projects from './Projects.js'\n\nexport default props =\u003e (\n  \u003cdiv\u003e\n    \u003cProjects /\u003e\n  \u003c/div\u003e\n)\n```\n\n### Creating root app\n```javascript\nimport React from 'react'\nimport { render } from 'react-dom'\nimport { BrowserRouter as Router } from 'react-router-dom'\nimport { Tap } from 'react-hydrate'\nimport App from './App'\n\nrender((\n  \u003cRouter\u003e\n    \u003cTap hydrate={window.__hydrate || null}\u003e\n      \u003cApp /\u003e\n    \u003c/Tap\u003e\n  \u003c/Router\u003e\n), document.getElementById('root'))\n```\n\n### Server\n```javascript\nimport React from 'react'\nimport { renderToString } from 'react-dom/server'\nimport { StaticRouter: Router } from 'react-router'\nimport { Tap, createStore } from 'react-hydrate'\nimport { asyncRender } from 'react-hydrate/dist/server'\nimport App from './App.js'\n\napp.use((req, res) =\u003e {\n  const ctx = {}\n  const store = createStore({})\n\n  const Root = (\n    \u003cRouter location={req.url} context={ctx}\u003e\n      \u003cTap hydrate={store}\u003e\n        \u003cApp /\u003e\n      \u003c/Tap\u003e\n    \u003c/Router\u003e\n  )\n\n  asyncRender(Root).then(() =\u003e {\n    const state = store.getState()\n    const content = renderToString(Root)\n\n    if (ctx.url) {\n      res.writeHead(302, {\n        Location: ctx.url\n      })\n      res.end()\n    } else {\n      res.send(`\n        \u003c!DOCTYPE html\u003e\n        \u003chtml\u003e\n          \u003chead\u003e\u003c/head\u003e\n          \u003cbody\u003e\n            ${content}\n            \u003cscript\u003e\n              window.__hydrate = ${JSON.stringify(state)}\n            \u003c/script\u003e\n            \u003cscript src=\"/index.js\"\u003e\u003c/script\u003e\n          \u003c/body\u003e\n        \u003c/html\u003e\n      `)\n      res.end()\n      store.clearState()\n    }\n  })\n})\n```\n\n## Dependencies\n- [react-tree-walker:](https://github.com/ctrlplusb/react-tree-walker) Walk a React element tree. by [@ctrlplusb](https://github.com/ctrlplusb)\n\nMIT License\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Festrattonbailey%2Freact-hydrate","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Festrattonbailey%2Freact-hydrate","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Festrattonbailey%2Freact-hydrate/lists"}