{"id":24288177,"url":"https://github.com/bjoluc/next-redux-cookie-wrapper","last_synced_at":"2025-04-07T12:03:51.917Z","repository":{"id":36411315,"uuid":"223505441","full_name":"bjoluc/next-redux-cookie-wrapper","owner":"bjoluc","description":"Sync a subset of your Redux state with cookies in Next.js :cookie: :sparkles:","archived":false,"fork":false,"pushed_at":"2023-03-15T04:41:24.000Z","size":4260,"stargazers_count":113,"open_issues_count":5,"forks_count":4,"subscribers_count":4,"default_branch":"main","last_synced_at":"2025-03-31T11:01:46.680Z","etag":null,"topics":["cookies","next-redux-wrapper","nextjs","redux","ssr"],"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/bjoluc.png","metadata":{"files":{"readme":"README.md","changelog":null,"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,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-11-22T23:56:16.000Z","updated_at":"2024-12-14T15:35:55.000Z","dependencies_parsed_at":"2024-06-18T18:34:24.686Z","dependency_job_id":"d413a353-6f12-4a3b-8b67-83b1d28d3f2b","html_url":"https://github.com/bjoluc/next-redux-cookie-wrapper","commit_stats":{"total_commits":113,"total_committers":5,"mean_commits":22.6,"dds":"0.37168141592920356","last_synced_commit":"cc0d54ba3d6760b8709dfb78645dedeaf0d5b2f4"},"previous_names":[],"tags_count":14,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bjoluc%2Fnext-redux-cookie-wrapper","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bjoluc%2Fnext-redux-cookie-wrapper/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bjoluc%2Fnext-redux-cookie-wrapper/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bjoluc%2Fnext-redux-cookie-wrapper/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bjoluc","download_url":"https://codeload.github.com/bjoluc/next-redux-cookie-wrapper/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247608150,"owners_count":20965952,"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":["cookies","next-redux-wrapper","nextjs","redux","ssr"],"created_at":"2025-01-16T09:53:44.581Z","updated_at":"2025-04-07T12:03:51.891Z","avatar_url":"https://github.com/bjoluc.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# next-redux-cookie-wrapper\n\n[![npm (tag)](https://img.shields.io/npm/v/next-redux-cookie-wrapper/latest)](https://www.npmjs.com/package/next-redux-cookie-wrapper)\n[![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/bjoluc/next-redux-cookie-wrapper/build.yml)](https://github.com/bjoluc/next-redux-cookie-wrapper/actions)\n[![codecov](https://codecov.io/gh/bjoluc/next-redux-cookie-wrapper/branch/master/graph/badge.svg)](https://codecov.io/gh/bjoluc/next-redux-cookie-wrapper)\n[![XO code style](https://img.shields.io/badge/code_style-XO-5ed9c7.svg)](https://github.com/xojs/xo)\n[![semantic-release](https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg)](https://github.com/semantic-release/semantic-release)\n\nA [next-redux-wrapper](https://github.com/kirill-konshin/next-redux-wrapper/) extension to sync a subset of a client's [Redux](https://redux.js.org/) state with cookies such that it survives page reloads and is available to the server during SSR :cookie: :sparkles:\n\n## Motivation\n\nWhen it comes to Redux state persistence, [Redux Persist](https://github.com/rt2zz/redux-persist) is a popular choice.\nWith Next.js, however, the persisted state is (without further ado) not available during SSR.\nHence, the first render on the client side may largely differ from the server-rendered markup.\nA solution to this is a storage method that is available to both the server and the client by default: Cookies.\n\nThis library started as a drop-in replacement for [next-redux-wrapper](https://github.com/kirill-konshin/next-redux-wrapper/) that built upon Redux Persist and a [storage adapter for cookies](https://github.com/abersager/redux-persist-cookie-storage).\nHowever, in response to `getStaticProps()` and `getServerSideProps()` being introduced in Next.js, it has been rewritten and the tooling has been simplified significantly.\nWhat remains is a single Redux middleware and a tiny wrapper around the `makeStore()` function.\n\n## How does it work?\n\nOn the server, a wrapper around `makeStore()` passes the Next.js context to the middleware via an action.\nThe middleware then reads the cookies and dispatches an initial `HYDRATE` action with the client's state.\nOn server-side state changes, `set-cookie` headers are set to update the client's cookies.\n\nSimilarly, the client updates cookies whenever a relevant portion of the state changes.\nMoreover, the `HYDRATE` action is intercepted on the client and the configured state subtrees are (by default) parsed from the cookies instead of the retrieved JSON data.\nThis way, incoming state updates from `getStaticProps()` do not overwrite the synced state subtrees as `getStaticProps()` does not update the cookies.\nYou can opt out of this behavior on a per-state-subtree basis and instead always receive the server's state in the `HYDRATE` reducer if you wish to handle state portions from `getStaticProps()` on your own.\n\nSome words about compression:\nBy default, the serialized cookie state is compressed using [lz-string](https://github.com/pieroxy/lz-string) to keep the cookie size small.\nYou can disable compression globally or per state subtree by setting the `compress` option to `false`.\n\n## Setup\n\n\u003e **TL;DR**\n\u003e\n\u003e For a quick working example, check out the demo project in this repository.\n\u003e It uses [Redux Toolkit](https://redux-toolkit.js.org/) but that should not discourage you.\n\u003e  * Clone the repository\n\u003e  * Make sure you have have NPM v7 or later installed (`npm i -g \"npm@\u003e=7\"`; required for the workspaces feature)\n\u003e  * Run `npm install` in the root directory\n\u003e  * `cd demo \u0026\u0026 npm start`\n\u003e  * Inspect the setup in [`store.ts`](https://github.com/bjoluc/next-redux-cookie-wrapper/tree/main/demo/store.ts)\n\nIf you do not have next-redux-wrapper set up, follow their [installation instructions](https://github.com/kirill-konshin/next-redux-wrapper/#installation).\nAfterwards, install `next-redux-cookie-wrapper`:\n```\nnpm install --save next-redux-cookie-wrapper\n```\n\nand configure your store to use `nextReduxCookieMiddleware` by passing it to `createStore()` and wrapping your `makeStore()` function with `wrapMakeStore()`:\n\n```diff\n+ import {nextReduxCookieMiddleware, wrapMakeStore} from \"next-redux-cookie-wrapper\";\n\n...\n\n- const makeStore = () =\u003e createStore(reducer);\n+ const makeStore = wrapMakeStore(() =\u003e\n+   createStore(\n+     reducer,\n+     applyMiddleware(\n+       nextReduxCookieMiddleware({\n+         subtrees: [\"my.subtree\"],\n+       })\n+     )\n+   )\n+ );\n```\n\nThat's it! The state of `my.subtree` should now be synced with a cookie called `my.subtree` and available on the server during SSR.\nIf not, you can set the debug flag of `next-redux-wrapper` to `true` to get some insights on the state:\n\n```ts\nexport const wrapper = createWrapper\u003cAppStore\u003e(makeStore, {debug: true});\n```\n\n### Usage with Redux Toolkit\n\nWhen using [Redux Toolkit](https://redux-toolkit.js.org/), it is important that `nextReduxCookieMiddleware` is used before any of the default middlewares:\n\n```ts\nconst makeStore = wrapMakeStore(() =\u003e\n  configureStore({\n    reducer: {...},\n    middleware: (getDefaultMiddleware) =\u003e\n      getDefaultMiddleware().prepend(\n        nextReduxCookieMiddleware({\n          subtrees: [\"my.subtree\"],\n        })\n      ),\n  })\n);\n```\n\nThe reason for this is that Redux Toolkit by default adds a [serializability middleware](https://redux-toolkit.js.org/api/serializabilityMiddleware) that would complain about the `SERVE_COOKIES` action which `wrapMakeStore()` uses to pass the Next.js context to `nextReduxCookieMiddleware`.\nWhen `nextReduxCookieMiddleware` is invoked before the serializability middleware, it catches the `SERVE_COOKIES` action before it reaches that middleware.\nAlternatively, you can also configure the serializability middleware to ignore the `SERVE_COOKIES` action, should you prefer that.\n\n## Configuration\n\nFor the configuration options of `nextReduxCookieMiddleware`, please refer to [the API documentation](https://next-redux-cookie-wrapper.js.org/interfaces/NextReduxCookieMiddlewareConfig.html).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbjoluc%2Fnext-redux-cookie-wrapper","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbjoluc%2Fnext-redux-cookie-wrapper","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbjoluc%2Fnext-redux-cookie-wrapper/lists"}