{"id":13776785,"url":"https://github.com/polemius/recoil-persist","last_synced_at":"2025-05-16T05:05:02.865Z","repository":{"id":38214629,"uuid":"265155789","full_name":"polemius/recoil-persist","owner":"polemius","description":"Package for recoil state manager to persist and rehydrate store","archived":false,"fork":false,"pushed_at":"2023-12-22T04:07:26.000Z","size":1303,"stargazers_count":354,"open_issues_count":33,"forks_count":40,"subscribers_count":6,"default_branch":"master","last_synced_at":"2025-05-09T03:43:12.067Z","etag":null,"topics":["atoms","localstorage","recoil","recoiljs","sessionstorage","storage"],"latest_commit_sha":null,"homepage":"https://polemius.dev/recoil-persist/","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/polemius.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2020-05-19T05:40:32.000Z","updated_at":"2025-03-22T10:10:15.000Z","dependencies_parsed_at":"2024-01-13T05:11:51.637Z","dependency_job_id":"b130f16c-d0ce-4139-833b-2831840071a1","html_url":"https://github.com/polemius/recoil-persist","commit_stats":{"total_commits":102,"total_committers":9,"mean_commits":"11.333333333333334","dds":0.3431372549019608,"last_synced_commit":"5300f3ce12c675097345b91383583fe986e571d3"},"previous_names":[],"tags_count":30,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/polemius%2Frecoil-persist","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/polemius%2Frecoil-persist/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/polemius%2Frecoil-persist/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/polemius%2Frecoil-persist/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/polemius","download_url":"https://codeload.github.com/polemius/recoil-persist/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254471061,"owners_count":22076585,"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":["atoms","localstorage","recoil","recoiljs","sessionstorage","storage"],"created_at":"2024-08-03T18:00:33.028Z","updated_at":"2025-05-16T05:05:02.843Z","avatar_url":"https://github.com/polemius.png","language":"TypeScript","funding_links":[],"categories":["Libraries"],"sub_categories":["Javascript"],"readme":"# Recoil Persist\n\nTiny module for [recoil](https://recoiljs.org) to store and sync state to\n`Storage`. It is only 354 bytes (minified and gzipped). No dependencies.\n[Size Limit](https://github.com/ai/size-limit) controls the size.\n\n[Demo](https://polemius.dev/recoil-persist/)\n\nIf you are using recoil-persist with version 1.x.x please check\n[migration guide](https://github.com/polemius/recoil-persist#migration-from-version-1xx-to-2xx)\nto version 2.x.x.\n\n![Example of persist state in localStorage](example.gif)\n\n```js\nimport React from 'react'\nimport ReactDOM from 'react-dom'\nimport App from './App'\nimport { atom, RecoilRoot, useRecoilState } from 'recoil'\nimport { recoilPersist } from 'recoil-persist'\n\nconst { persistAtom } = recoilPersist()\n\nconst counterState = atom({\n  key: 'count',\n  default: 0,\n  effects_UNSTABLE: [persistAtom],\n})\n\nfunction App() {\n  const [count, setCount] = useRecoilState(counterState)\n  return (\n    \u003cdiv\u003e\n      \u003ch3\u003eCounter: {count}\u003c/h3\u003e\n      \u003cbutton onClick={() =\u003e setCount(count + 1)}\u003eIncrease\u003c/button\u003e\n      \u003cbutton onClick={() =\u003e setCount(count - 1)}\u003eDecrease\u003c/button\u003e\n    \u003c/div\u003e\n  )\n}\n\nReactDOM.render(\n  \u003cReact.StrictMode\u003e\n    \u003cRecoilRoot\u003e\n      \u003cApp /\u003e\n    \u003c/RecoilRoot\u003e\n  \u003c/React.StrictMode\u003e,\n  document.getElementById('root'),\n)\n```\n\n## Install\n\n```\nnpm install recoil-persist\n```\n\nor\n\n```\nyarn add recoil-persist\n```\n\nNow you could add persisting a state to your app:\n\n```diff\nimport React from 'react';\nimport ReactDOM from 'react-dom';\nimport App from './App';\nimport { RecoilRoot } from \"recoil\";\n+import { recoilPersist } from 'recoil-persist'\n\n+const { persistAtom } = recoilPersist()\n\nconst counterState = atom({\n  key: 'count',\n  default: 0,\n+ effects_UNSTABLE: [persistAtom],\n})\n\nfunction App() {\n  const [count, setCount] = useRecoilState(counterState)\n  return (\n    \u003cdiv\u003e\n      \u003ch3\u003eCounter: {count}\u003c/h3\u003e\n      \u003cbutton onClick={() =\u003e setCount(count + 1)}\u003eIncrease\u003c/button\u003e\n      \u003cbutton onClick={() =\u003e setCount(count - 1)}\u003eDecrease\u003c/button\u003e\n    \u003c/div\u003e\n  )\n}\n\nReactDOM.render(\n  \u003cReact.StrictMode\u003e\n    \u003cRecoilRoot\u003e\n      \u003cApp /\u003e\n    \u003c/RecoilRoot\u003e\n  \u003c/React.StrictMode\u003e,\n  document.getElementById('root'),\n)\n```\n\nAfter this each changes in atom will be store and sync to `localStorage`.\n\n## Usage\n\n```js\nimport { recoilPersist } from 'recoil-persist'\n\nconst { persistAtom } = recoilPersist({\n  key: 'recoil-persist', // this key is using to store data in local storage\n  storage: localStorage, // configure which storage will be used to store the data\n  converter: JSON // configure how values will be serialized/deserialized in storage\n})\n```\n\n![Example of persist state in localStorage](example.png)\n\n## Server Side Rendering\n\nIf you are using SSR you could see that error:\n\n```\nUnhandled Runtime Error\n\nError: Text content does not match server-rendered HTML.\n```\n\nIt happens because on server you don't have any storages and react renders component with default value.\nHowever in browser it is rendering with values from storage.\nTo prevent it we need to introduce hook for render with default value for the first time.\n\n```js\nconst defaultValue = [{ id: 1 }]\n\nexport const recoilTest = atom\u003c{ id: number }[]\u003e({\n  key: \"recoilTest\",\n  default: defaultValue,\n  effects_UNSTABLE: [persistAtom],\n});\n\nexport function useSSR() {\n  const [isInitial, setIsInitial] = useState(true);\n  const [value, setValue] = useRecoilState(recoilTest);\n\n  useEffect(() =\u003e {\n    setIsInitial(false);\n  }, []);\n\n  return [isInitial ? defaultValue : value, setValue] as const;\n}\n\n\nexport default function Component() {\n  const [text, setText] = useSSR();\n\n  // rest of the code\n}\n```\n\n\n## API\n\n### recoilPersist(config)\n\n#### config parameter\n\n```js\ntype config.key = String\n```\n\nDefault value of `config.key` is `recoil-persist`. This key is using to store\ndata in storage.\n\n```js\ntype config.storage = Storage\n```\n\nSet `config.storage` with `sessionStorage` or other `Storage` implementation to\nchange storage target. Otherwise `localStorage` is used (default).\n\n```js\ntype config.converter = {\n  stringify: (value: any) =\u003e string\n  parse: (value: string) =\u003e any\n}\n```\n\nSet `config.converter` to an object which implements both `stringify` and `parse` functions to convert state values to and from strings. One use of this would be to wrap the standard `JSON.stringify` and `JSON.parse` functions, e.g. to insert your own `reviver` and `replacer` functions:\n\n```js\n{\n  parse: (value) =\u003e JSON.parse(value, myCustomReviver),\n  stringify: (value) =\u003e  JSON.stringify(value, myCustomReplacer)\n};\n```\n\n## Migration from version 1.x.x to 2.x.x\n\nThe API changed from version 1.x.x.\n\nTo update your code just use this migration guide:\n\n```diff\nimport React from 'react';\nimport ReactDOM from 'react-dom';\nimport App from './App';\nimport { RecoilRoot } from \"recoil\";\nimport { recoilPersist } from 'recoil-persist' // import stay the same\n\nconst {\n-  RecoilPersist,\n-  updateState\n+  persistAtom\n} = recoilPersist(\n-   ['count'], // no need for specifying atoms keys\n    {\n        key: 'recoil-persist', // configuration stay the same too\n        storage: localStorage\n    }\n)\n\nconst counterState = atom({\n  key: 'count',\n  default: 0,\n- persistence_UNSTABLE: { // Please remove persistence_UNSTABLE from atom definition\n-   type: 'log',\n- },\n+ effects_UNSTABLE: [persistAtom], // Please add effects_UNSTABLE key to atom definition\n})\n\nfunction App() {\n  const [count, setCount] = useRecoilState(counterState)\n  return (\n    \u003cdiv\u003e\n      \u003ch3\u003eCounter: {count}\u003c/h3\u003e\n      \u003cbutton onClick={() =\u003e setCount(count + 1)}\u003eIncrease\u003c/button\u003e\n      \u003cbutton onClick={() =\u003e setCount(count - 1)}\u003eDecrease\u003c/button\u003e\n    \u003c/div\u003e\n  )\n}\n\nReactDOM.render(\n  \u003cReact.StrictMode\u003e\n-   \u003cRecoilRoot initializeState={({set}) =\u003e updateState({set})\u003e\n+   \u003cRecoilRoot\u003e // Please remove updateState function from initiallizeState\n-     \u003cRecoilPersist /\u003e // and also remove RecoilPersist component\n      \u003cApp /\u003e\n    \u003c/RecoilRoot\u003e\n  \u003c/React.StrictMode\u003e,\n  document.getElementById('root')\n);\n```\n\n## Demo\n\n```\n$ git clone git@github.com:polemius/recoil-persist.git\n$ cd recoil-persist\n$ npm install\n$ npm run start\n```\n\nPlease open [localhost:1234](http://localhost:1234).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpolemius%2Frecoil-persist","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpolemius%2Frecoil-persist","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpolemius%2Frecoil-persist/lists"}