{"id":13527648,"url":"https://github.com/kirill-konshin/next-redux-wrapper","last_synced_at":"2025-05-13T23:05:06.350Z","repository":{"id":37430933,"uuid":"82350531","full_name":"kirill-konshin/next-redux-wrapper","owner":"kirill-konshin","description":"Redux wrapper for Next.js","archived":false,"fork":false,"pushed_at":"2023-08-22T21:18:40.000Z","size":2311,"stargazers_count":2686,"open_issues_count":58,"forks_count":266,"subscribers_count":21,"default_branch":"8.x","last_synced_at":"2025-05-12T00:02:28.288Z","etag":null,"topics":["isomorphic","nextjs","react","react-redux","redux","redux-saga","redux-toolkit"],"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/kirill-konshin.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","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},"funding":{"patreon":"kirill_konshin"}},"created_at":"2017-02-18T00:44:04.000Z","updated_at":"2025-05-06T10:15:06.000Z","dependencies_parsed_at":"2024-06-18T11:18:05.407Z","dependency_job_id":null,"html_url":"https://github.com/kirill-konshin/next-redux-wrapper","commit_stats":{"total_commits":162,"total_committers":51,"mean_commits":3.176470588235294,"dds":0.5308641975308642,"last_synced_commit":"286f756acf91224dddae62f81b0560ad432b3b80"},"previous_names":[],"tags_count":44,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kirill-konshin%2Fnext-redux-wrapper","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kirill-konshin%2Fnext-redux-wrapper/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kirill-konshin%2Fnext-redux-wrapper/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kirill-konshin%2Fnext-redux-wrapper/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/kirill-konshin","download_url":"https://codeload.github.com/kirill-konshin/next-redux-wrapper/tar.gz/refs/heads/8.x","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254040621,"owners_count":22004581,"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":["isomorphic","nextjs","react","react-redux","redux","redux-saga","redux-toolkit"],"created_at":"2024-08-01T06:01:55.449Z","updated_at":"2025-05-13T23:05:01.295Z","avatar_url":"https://github.com/kirill-konshin.png","language":"TypeScript","funding_links":["https://patreon.com/kirill_konshin"],"categories":["TypeScript","miscellaneous"],"sub_categories":[],"readme":"# Redux Wrapper for Next.js \u003c!-- omit in toc --\u003e\n\n[![npm version](https://badge.fury.io/js/next-redux-wrapper.svg)](https://www.npmjs.com/package/next-redux-wrapper)\n![Build status](https://travis-ci.org/kirill-konshin/next-redux-wrapper.svg?branch=master)\n[![Coverage Status](https://coveralls.io/repos/github/kirill-konshin/next-redux-wrapper/badge.svg?branch=master)](https://coveralls.io/github/kirill-konshin/next-redux-wrapper?branch=master)\n\nA HOC that brings Next.js and Redux together\n\n:warning: The current version of this library only works with Next.js 9.3 and newer. If you are required to use Next.js 6-9 you can use version 3-5 of this library, see [branches](https://github.com/kirill-konshin/next-redux-wrapper/branches). Otherwise, consider upgrading Next.js. :warning:\n\nContents:\n\n- [Motivation](#motivation)\n- [Installation](#installation)\n- [Usage](#usage)\n  - [State reconciliation during hydration](#state-reconciliation-during-hydration)\n  - [Configuration](#configuration)\n  - [getStaticProps](#getstaticprops)\n  - [getServerSideProps](#getserversideprops)\n  - [Page.getInitialProps](#pagegetinitialprops)\n  - [App](#app)\n  - [App and getServerSideProps or getStaticProps at page level](#app-and-getserversideprops-or-getstaticprops-at-page-level)\n- [How it works](#how-it-works)\n- [Tips and Tricks](#tips-and-tricks)\n  - [Redux Toolkit](#redux-toolkit)\n  - [Server and Client state separation](#server-and-client-state-separation)\n  - [Document](#document)\n  - [Error Pages](#error-pages)\n  - [Async actions](#async-actions)\n  - [Custom serialization and deserialization](#custom-serialization-and-deserialization)\n  - [Usage with Redux Saga](#usage-with-redux-saga)\n  - [Usage with Redux Persist](#usage-with-redux-persist)\n- [Upgrade from 6.x to 7.x](#upgrade-from-6x-to-7x)\n- [Upgrade from 5.x to 6.x](#upgrade-from-5x-to-6x)\n- [Upgrade from 1.x to 2.x](#upgrade-from-1x-to-2x)\n- [Resources](#resources)\n\n# Motivation\n\nSetting up Redux for static apps is rather simple: a single Redux store has to be created that is provided to all pages.\n\nWhen Next.js static site generator or server side rendering is involved, however, things start to get complicated as another store instance is needed on the server to render Redux-connected components.\n\nFurthermore, access to the Redux `Store` may also be needed during a page's `getInitialProps`.\n\nThis is where `next-redux-wrapper` comes in handy: It automatically creates the store instances for you and makes sure they all have the same state.\n\nMoreover it allows to properly handle complex cases like `App.getInitialProps` (when using `pages/_app`) together with `getStaticProps` or `getServerSideProps` at individual page level.\n\nLibrary provides uniform interface no matter in which Next.js lifecycle method you would like to use the `Store`.\n\nIn Next.js example https://github.com/vercel/next.js/blob/canary/examples/with-redux-thunk/store.js#L23 store is being replaced on navigation. Redux will re-render components even with memoized selectors (`createSelector` from `recompose`) if `store` is replaced: https://codesandbox.io/s/redux-store-change-kzs8q, which may affect performance of the app by causing a huge re-render of everything, even what did not change. This library makes sure `store` remains the same.\n\n# Installation\n\n```bash\nnpm install next-redux-wrapper react-redux --save\n```\n\nNote that `next-redux-wrapper` requires `react-redux` as peer dependency.\n\n# Usage\n\nLive example: https://codesandbox.io/s/next-redux-wrapper-demo-7n2t5.\n\nAll examples are written in TypeScript. If you're using plain JavaScript just omit type declarations. These examples use vanilla Redux, if you're using Redux Toolkit, please refer to [dedicated example](#redux-toolkit).\n\nNext.js has several data fetching mechanisms, this library can attach to any of them. But first you have to write some common code.\n\n**Please note that your reducer _must_ have the `HYDRATE` action handler. `HYDRATE` action handler must properly reconciliate the hydrated state on top of the existing state (if any).** This behavior was added in version 6 of this library. We'll talk about this special action later.\n\nCreate a file named `store.ts`:\n\n```typescript\n// store.ts\n\nimport {createStore, AnyAction, Store} from 'redux';\nimport {createWrapper, Context, HYDRATE} from 'next-redux-wrapper';\n\nexport interface State {\n  tick: string;\n}\n\n// create your reducer\nconst reducer = (state: State = {tick: 'init'}, action: AnyAction) =\u003e {\n  switch (action.type) {\n    case HYDRATE:\n      // Attention! This will overwrite client state! Real apps should use proper reconciliation.\n      return {...state, ...action.payload};\n    case 'TICK':\n      return {...state, tick: action.payload};\n    default:\n      return state;\n  }\n};\n\n// create a makeStore function\nconst makeStore = (context: Context) =\u003e createStore(reducer);\n\n// export an assembled wrapper\nexport const wrapper = createWrapper\u003cStore\u003cState\u003e\u003e(makeStore, {debug: true});\n```\n\n\u003cdetails\u003e\n\u003csummary\u003eSame code in JavaScript (without types)\u003c/summary\u003e\n\n```js\n// store.js\n\nimport {createStore} from 'redux';\nimport {createWrapper, HYDRATE} from 'next-redux-wrapper';\n\n// create your reducer\nconst reducer = (state = {tick: 'init'}, action) =\u003e {\n  switch (action.type) {\n    case HYDRATE:\n      return {...state, ...action.payload};\n    case 'TICK':\n      return {...state, tick: action.payload};\n    default:\n      return state;\n  }\n};\n\n// create a makeStore function\nconst makeStore = context =\u003e createStore(reducer);\n\n// export an assembled wrapper\nexport const wrapper = createWrapper(makeStore, {debug: true});\n```\n\n\u003c/details\u003e\n\n## `wrapper.useWrappedStore`\n\nIt is highly recommended to use `pages/_app` to wrap all pages at once, otherwise due to potential race conditions you may get `Cannot update component while rendering another component`:\n\n```tsx\nimport React, {FC} from 'react';\nimport {Provider} from 'react-redux';\nimport {AppProps} from 'next/app';\nimport {wrapper} from '../components/store';\n\nconst MyApp: FC\u003cAppProps\u003e = ({Component, ...rest}) =\u003e {\n  const {store, props} = wrapper.useWrappedStore(rest);\n  return (\n    \u003cProvider store={store}\u003e\n      \u003cComponent {...props.pageProps} /\u003e\n    \u003c/Provider\u003e\n  );\n};\n```\n\nInstead of `wrapper.useWrappedStore` you can also use legacy HOC, that can work with class-based components.\n\n:warning: Next.js provides [generic `getInitialProps`](https://github.com/vercel/next.js/blob/canary/packages/next/pages/_app.tsx#L21) when using `class MyApp extends App` which will be picked up by wrapper, so you **must not extend `App`** as you'll be opted out of Automatic Static Optimization: https://err.sh/next.js/opt-out-auto-static-optimization. Just export a regular Functional Component as in the example above.\n\n```tsx\nimport React from 'react';\nimport {wrapper} from '../components/store';\nimport {AppProps} from 'next/app';\n\nclass MyApp extends React.Component\u003cAppProps\u003e {\n  render() {\n    const {Component, pageProps} = this.props;\n    return \u003cComponent {...pageProps} /\u003e;\n  }\n}\n\nexport default wrapper.withRedux(MyApp);\n```\n\n## State reconciliation during hydration\n\nEach time when pages that have `getStaticProps` or `getServerSideProps` are opened by user the `HYDRATE` action will be dispatched. This may happen during initial page load and during regular page navigation. The `payload` of this action will contain the `state` at the moment of static generation or server side rendering, so your reducer must merge it with existing client state properly.\n\nSimplest way is to use [server and client state separation](#server-and-client-state-separation).\n\nAnother way is to use https://github.com/benjamine/jsondiffpatch to analyze diff and apply it properly:\n\n```tsx\nimport {HYDRATE} from 'next-redux-wrapper';\n\n// create your reducer\nconst reducer = (state = {tick: 'init'}, action) =\u003e {\n  switch (action.type) {\n    case HYDRATE:\n      const stateDiff = diff(state, action.payload) as any;\n      const wasBumpedOnClient = stateDiff?.page?.[0]?.endsWith('X'); // or any other criteria\n      return {\n        ...state,\n        ...action.payload,\n        page: wasBumpedOnClient ? state.page : action.payload.page, // keep existing state or use hydrated\n      };\n    case 'TICK':\n      return {...state, tick: action.payload};\n    default:\n      return state;\n  }\n};\n```\n\nOr [like this](https://github.com/zeit/next.js/blob/canary/examples/with-redux-wrapper/store/store.js) (from [with-redux-wrapper example](https://github.com/zeit/next.js/tree/canary/examples/with-redux-wrapper) in Next.js repo):\n\n```js\nconst reducer = (state, action) =\u003e {\n  if (action.type === HYDRATE) {\n    const nextState = {\n      ...state, // use previous state\n      ...action.payload, // apply delta from hydration\n    };\n    if (state.count) nextState.count = state.count; // preserve count value on client side navigation\n    return nextState;\n  } else {\n    return combinedReducer(state, action);\n  }\n};\n```\n\n## Configuration\n\nThe `createWrapper` function accepts `makeStore` as its first argument. The `makeStore` function should return a new Redux `Store` instance each time it's called. No memoization is needed here, it is automatically done inside the wrapper.\n\n`createWrapper` also optionally accepts a config object as a second parameter:\n\n- `debug` (optional, boolean) : enable debug logging\n- `serializeState` and `deserializeState`: custom functions for serializing and deserializing the redux state, see\n  [Custom serialization and deserialization](#custom-serialization-and-deserialization).\n\nWhen `makeStore` is invoked it is provided with a Next.js context, which could be [`NextPageContext`](https://nextjs.org/docs/api-reference/data-fetching/getInitialProps) or [`AppContext`](https://nextjs.org/docs/advanced-features/custom-app) or [`getStaticProps`](https://nextjs.org/docs/basic-features/data-fetching#getstaticprops-static-generation) or [`getServerSideProps`](https://nextjs.org/docs/basic-features/data-fetching#getserversideprops-server-side-rendering) context depending on which lifecycle function you will wrap.\n\nSome of those contexts (`getServerSideProps` always, and `NextPageContext`, `AppContext` sometimes if page is rendered on server) can have request and response related properties:\n\n- `req` (`IncomingMessage`)\n- `res` (`ServerResponse`)\n\nAlthough it is possible to create server or client specific logic in both `makeStore`, I highly recommend that they do not have different behavior. This may cause errors and checksum mismatches which in turn will ruin the whole purpose of server rendering.\n\n## getStaticProps\n\nThis section describes how to attach to [getStaticProps](https://nextjs.org/docs/basic-features/data-fetching#getstaticprops-static-generation) lifecycle function.\n\nLet's create a page in `pages/pageName.tsx`:\n\n```typescript\nimport React from 'react';\nimport {NextPage} from 'next';\nimport {useSelector} from 'react-redux';\nimport {wrapper, State} from '../store';\n\nexport const getStaticProps = wrapper.getStaticProps(store =\u003e ({preview}) =\u003e {\n  console.log('2. Page.getStaticProps uses the store to dispatch things');\n  store.dispatch({\n    type: 'TICK',\n    payload: 'was set in other page ' + preview,\n  });\n});\n\n// you can also use `connect()` instead of hooks\nconst Page: NextPage = () =\u003e {\n  const {tick} = useSelector\u003cState, State\u003e(state =\u003e state);\n  return \u003cdiv\u003e{tick}\u003c/div\u003e;\n};\n\nexport default Page;\n```\n\n\u003cdetails\u003e\n\u003csummary\u003eSame code in JavaScript (without types)\u003c/summary\u003e\n\n```js\nimport React from 'react';\nimport {useSelector} from 'react-redux';\nimport {wrapper} from '../store';\n\nexport const getStaticProps = wrapper.getStaticProps(store =\u003e ({preview}) =\u003e {\n  console.log('2. Page.getStaticProps uses the store to dispatch things');\n  store.dispatch({\n    type: 'TICK',\n    payload: 'was set in other page ' + preview,\n  });\n});\n\n// you can also use `connect()` instead of hooks\nconst Page = () =\u003e {\n  const {tick} = useSelector(state =\u003e state);\n  return \u003cdiv\u003e{tick}\u003c/div\u003e;\n};\n\nexport default Page;\n```\n\n\u003c/details\u003e\n\n:warning: **Each time when pages that have `getStaticProps` are opened by user the `HYDRATE` action will be dispatched.** The `payload` of this action will contain the `state` at the moment of static generation, it will not have client state, so your reducer must merge it with existing client state properly. More about this in [Server and Client State Separation](#server-and-client-state-separation).\n\nAlthough you can wrap individual pages (and not wrap the `pages/_app`) it is not recommended, see last paragraph in [usage section](#usage).\n\n## getServerSideProps\n\nThis section describes how to attach to [getServerSideProps](https://nextjs.org/docs/basic-features/data-fetching#getserversideprops-server-side-rendering) lifecycle function.\n\nLet's create a page in `pages/pageName.tsx`:\n\n```typescript\nimport React from 'react';\nimport {NextPage} from 'next';\nimport {connect} from 'react-redux';\nimport {wrapper, State} from '../store';\n\nexport const getServerSideProps = wrapper.getServerSideProps(store =\u003e ({req, res, ...etc}) =\u003e {\n  console.log('2. Page.getServerSideProps uses the store to dispatch things');\n  store.dispatch({type: 'TICK', payload: 'was set in other page'});\n});\n\n// Page itself is not connected to Redux Store, it has to render Provider to allow child components to connect to Redux Store\nconst Page: NextPage\u003cState\u003e = ({tick}) =\u003e \u003cdiv\u003e{tick}\u003c/div\u003e;\n\n// you can also use Redux `useSelector` and other hooks instead of `connect()`\nexport default connect((state: State) =\u003e state)(Page);\n```\n\n\u003cdetails\u003e\n\u003csummary\u003eSame code in JavaScript (without types)\u003c/summary\u003e\n\n```js\nimport React from 'react';\nimport {connect} from 'react-redux';\nimport {wrapper} from '../store';\n\nexport const getServerSideProps = wrapper.getServerSideProps(store =\u003e ({req, res, ...etc}) =\u003e {\n  console.log('2. Page.getServerSideProps uses the store to dispatch things');\n  store.dispatch({type: 'TICK', payload: 'was set in other page'});\n});\n\n// Page itself is not connected to Redux Store, it has to render Provider to allow child components to connect to Redux Store\nconst Page = ({tick}) =\u003e \u003cdiv\u003e{tick}\u003c/div\u003e;\n\n// you can also use Redux `useSelector` and other hooks instead of `connect()`\nexport default connect(state =\u003e state)(Page);\n```\n\n\u003c/details\u003e\n\n:warning: **Each time when pages that have `getServerSideProps` are opened by user the `HYDRATE` action will be dispatched.** The `payload` of this action will contain the `state` at the moment of server side rendering, it will not have client state, so your reducer must merge it with existing client state properly. More about this in [Server and Client State Separation](#server-and-client-state-separation).\n\nAlthough you can wrap individual pages (and not wrap the `pages/_app`) it is not recommended, see last paragraph in [usage section](#usage).\n\n## `Page.getInitialProps`\n\n```typescript\nimport React, {Component} from 'react';\nimport {NextPage} from 'next';\nimport {wrapper, State} from '../store';\n\n// you can also use `connect()` instead of hooks\nconst Page: NextPage = () =\u003e {\n  const {tick} = useSelector\u003cState, State\u003e(state =\u003e state);\n  return \u003cdiv\u003e{tick}\u003c/div\u003e;\n};\n\nPage.getInitialProps = wrapper.getInitialPageProps(store =\u003e ({pathname, req, res}) =\u003e {\n  console.log('2. Page.getInitialProps uses the store to dispatch things');\n  store.dispatch({\n    type: 'TICK',\n    payload: 'was set in error page ' + pathname,\n  });\n});\n\nexport default Page;\n```\n\n\u003cdetails\u003e\n\u003csummary\u003eSame code in JavaScript (without types)\u003c/summary\u003e\n\n```js\nimport React, {Component} from 'react';\nimport {wrapper} from '../store';\n\n// you can also use `connect()` instead of hooks\nconst Page = () =\u003e {\n  const {tick} = useSelector(state =\u003e state);\n  return \u003cdiv\u003e{tick}\u003c/div\u003e;\n};\n\nPage.getInitialProps = wrapper.getInitialPageProps(store =\u003e ({pathname, req, res}) =\u003e {\n  console.log('2. Page.getInitialProps uses the store to dispatch things');\n  store.dispatch({\n    type: 'TICK',\n    payload: 'was set in error page ' + pathname,\n  });\n});\n\nexport default Page;\n```\n\n\u003c/details\u003e\n\nKeep in mind that `req` and `res` may not be available if `getInitialProps` is called on client side.\n\nStateless function component also can be replaced with class:\n\n```js\nclass Page extends Component {\n\n    public static getInitialProps = wrapper.getInitialPageProps(store =\u003e () =\u003e ({ ... }));\n\n    render() {\n        // stuff\n    }\n}\n\nexport default Page;\n```\n\nAlthough you can wrap individual pages (and not wrap the `pages/_app`) it is not recommended, see last paragraph in [usage section](#usage).\n\n## App\n\n:warning: You can dispatch actions from the `pages/_app` too. But this mode is not compatible with [Next.js 9's Auto Partial Static Export](https://nextjs.org/blog/next-9#automatic-partial-static-export) feature, see the [explanation below](#automatic-partial-static-export).\n\nThe wrapper can also be attached to your `_app` component (located in `/pages`). All other components can use the `connect` function of `react-redux`.\n\n```tsx\n// pages/_app.tsx\n\nimport React from 'react';\nimport App, {AppInitialProps} from 'next/app';\nimport {wrapper} from '../components/store';\nimport {State} from '../components/reducer';\n\n// Since you'll be passing more stuff to Page\ndeclare module 'next/dist/next-server/lib/utils' {\n  export interface NextPageContext {\n    store: Store\u003cState\u003e;\n  }\n}\n\nclass MyApp extends App\u003cAppInitialProps\u003e {\n  public static getInitialProps = wrapper.getInitialAppProps(store =\u003e async context =\u003e {\n    store.dispatch({type: 'TOE', payload: 'was set in _app'});\n\n    return {\n      pageProps: {\n        // https://nextjs.org/docs/advanced-features/custom-app#caveats\n        ...(await App.getInitialProps(context)).pageProps,\n        // Some custom thing for all pages\n        pathname: ctx.pathname,\n      },\n    };\n  });\n\n  public render() {\n    const {Component, pageProps} = this.props;\n\n    return \u003cComponent {...pageProps} /\u003e;\n  }\n}\n\nexport default wrapper.withRedux(MyApp);\n```\n\n\u003cdetails\u003e\n\u003csummary\u003eSame code in JavaScript (without types)\u003c/summary\u003e\n\n```jsx\n// pages/_app.tsx\n\nimport React from 'react';\nimport App from 'next/app';\nimport {wrapper} from '../components/store';\n\nclass MyApp extends App {\n  static getInitialProps = wrapper.getInitialAppProps(store =\u003e async context =\u003e {\n    store.dispatch({type: 'TOE', payload: 'was set in _app'});\n\n    return {\n      pageProps: {\n        // https://nextjs.org/docs/advanced-features/custom-app#caveats\n        ...(await App.getInitialProps(context)).pageProps,\n        // Some custom thing for all pages\n        pathname: ctx.pathname,\n      },\n    };\n  });\n\n  render() {\n    const {Component, pageProps} = this.props;\n\n    return \u003cComponent {...pageProps} /\u003e;\n  }\n}\n\nexport default wrapper.withRedux(MyApp);\n```\n\n\u003c/details\u003e\n\nThen all pages can simply be connected (the example considers page components):\n\n```tsx\n// pages/xxx.tsx\n\nimport React from 'react';\nimport {NextPage} from 'next';\nimport {connect} from 'react-redux';\nimport {NextPageContext} from 'next';\nimport {State} from '../store';\n\nconst Page: NextPage\u003cState\u003e = ({foo, custom}) =\u003e (\n  \u003cdiv\u003e\n    \u003cdiv\u003eProp from Redux {foo}\u003c/div\u003e\n    \u003cdiv\u003eProp from getInitialProps {custom}\u003c/div\u003e\n  \u003c/div\u003e\n);\n\n// No need to wrap pages if App was wrapped\nPage.getInitialProps = ({store, pathname, query}: NextPageContext) =\u003e {\n  store.dispatch({type: 'FOO', payload: 'foo'}); // The component can read from the store's state when rendered\n  return {custom: 'custom'}; // You can pass some custom props to the component from here\n};\n\nexport default connect((state: State) =\u003e state)(Page);\n```\n\n\u003cdetails\u003e\n\u003csummary\u003eSame code in JavaScript (without types)\u003c/summary\u003e\n\n```jsx\n// pages/xxx.js\n\nimport React from 'react';\nimport {connect} from 'react-redux';\n\nconst Page = ({foo, custom}) =\u003e (\n  \u003cdiv\u003e\n    \u003cdiv\u003eProp from Redux {foo}\u003c/div\u003e\n    \u003cdiv\u003eProp from getInitialProps {custom}\u003c/div\u003e\n  \u003c/div\u003e\n);\n\n// No need to wrap pages if App was wrapped\nPage.getInitialProps = ({store, pathname, query}) =\u003e {\n  store.dispatch({type: 'FOO', payload: 'foo'}); // The component can read from the store's state when rendered\n  return {custom: 'custom'}; // You can pass some custom props to the component from here\n};\n\nexport default connect(state =\u003e state)(Page);\n```\n\n\u003c/details\u003e\n\n## App and `getServerSideProps` or `getStaticProps` at page level\n\nYou can also use `getServerSideProps` or `getStaticProps` at page level, in this case `HYDRATE` action will be dispatched twice: with state after `App.getInitialProps` and then with state after `getServerSideProps` or `getStaticProps`:\n\n- If you use `getServerSideProps` at page level then `store` in `getServerSideProps` will be executed after `App.getInitialProps` and will have state from it, so second `HYDRATE` will have full state from both\n- :warning: If you use `getStaticProps` at page level then `store` in `getStaticProps` will be executed at compile time and will **NOT** have state from `App.getInitialProps` because they are executed in different contexts and state cannot be shared. First `HYDRATE` actions state after `App.getInitialProps` and second will have state after `getStaticProps` (even though it was executed earlier in time).\n\nSimplest way to ensure proper merging is to drop initial values from `action.payload`:\n\n```typescript\nconst reducer = (state: State = {app: 'init', page: 'init'}, action: AnyAction) =\u003e {\n  switch (action.type) {\n    case HYDRATE:\n      if (action.payload.app === 'init') delete action.payload.app;\n      if (action.payload.page === 'init') delete action.payload.page;\n      return {...state, ...action.payload};\n    case 'APP':\n      return {...state, app: action.payload};\n    case 'PAGE':\n      return {...state, page: action.payload};\n    default:\n      return state;\n  }\n};\n```\n\n\u003cdetails\u003e\n\u003csummary\u003eSame code in JavaScript (without types)\u003c/summary\u003e\n\n```js\nconst reducer = (state = {app: 'init', page: 'init'}, action) =\u003e {\n  switch (action.type) {\n    case HYDRATE:\n      if (action.payload.app === 'init') delete action.payload.app;\n      if (action.payload.page === 'init') delete action.payload.page;\n      return {...state, ...action.payload};\n    case 'APP':\n      return {...state, app: action.payload};\n    case 'PAGE':\n      return {...state, page: action.payload};\n    default:\n      return state;\n  }\n};\n```\n\n\u003c/details\u003e\n\nAssume page only dispatches `PAGE` action and App only `APP`, this makes state merging safe.\n\nMore about that in [Server and Client state separation](#server-and-client-state-separation).\n\n# How it works\n\nUsing `next-redux-wrapper` (\"the wrapper\"), the following things happen on a request:\n\n- Phase 1: `getInitialProps`/`getStaticProps`/`getServerSideProps`\n\n  - The wrapper creates a server-side store (using `makeStore`) with an empty initial state. In doing so it also provides the `Request` and `Response` objects as options to `makeStore`.\n  - In App mode:\n    - The wrapper calls the `_app`'s `getInitialProps` function and passes the previously created store.\n    - Next.js takes the props returned from the `_app`'s `getInitialProps` method, along with the store's state.\n  - In per-page mode:\n    - The wrapper calls the Page's `getXXXProps` function and passes the previously created store.\n    - Next.js takes the props returned from the Page's `getXXXProps` method, along with the store's state.\n\n- Phase 2: SSR\n\n  - The wrapper creates a new store using `makeStore`\n  - The wrapper dispatches `HYDRATE` action with the previous store's state as `payload`\n  - That store is passed as a property to the `_app` or `page` component.\n  - **Connected components may alter the store's state, but the modified state will not be transferred to the client.**\n\n- Phase 3: Client\n  - The wrapper creates a new store\n  - The wrapper dispatches `HYDRATE` action with the state from Phase 1 as `payload`\n  - That store is passed as a property to the `_app` or `page` component.\n  - The wrapper persists the store in the client's window object, so it can be restored in case of HMR.\n\n**Note:** The client's state is not persisted across requests (i.e. Phase 1 always starts with an empty state).\nHence, it is reset on page reloads.\nConsider using [Redux persist](#usage-with-redux-persist) if you want to persist state between requests.\n\n## Tips and Tricks\n\n### Redux Toolkit\n\nSince version `7.0` first-class support of `@reduxjs/toolkit` has been added.\n\nFull example: https://github.com/kirill-konshin/next-redux-wrapper/blob/master/packages/demo-redux-toolkit.\n\n```ts\nimport {configureStore, createSlice, ThunkAction} from '@reduxjs/toolkit';\nimport {Action} from 'redux';\nimport {createWrapper, HYDRATE} from 'next-redux-wrapper';\n\nexport const subjectSlice = createSlice({\n  name: 'subject',\n\n  initialState: {} as any,\n\n  reducers: {\n    setEnt(state, action) {\n      return action.payload;\n    },\n  },\n\n  extraReducers: {\n    [HYDRATE]: (state, action) =\u003e {\n      console.log('HYDRATE', state, action.payload);\n      return {\n        ...state,\n        ...action.payload.subject,\n      };\n    },\n  },\n});\n\nconst makeStore = () =\u003e\n  configureStore({\n    reducer: {\n      [subjectSlice.name]: subjectSlice.reducer,\n    },\n    devTools: true,\n  });\n\nexport type AppStore = ReturnType\u003ctypeof makeStore\u003e;\nexport type AppState = ReturnType\u003cAppStore['getState']\u003e;\nexport type AppDispatch = AppStore['dispatch'];\nexport type AppThunk\u003cReturnType = void\u003e = ThunkAction\u003cReturnType, AppState, unknown, Action\u003e;\n\n// Use throughout your app instead of plain `useDispatch` and `useSelector`\nexport const useAppDispatch = () =\u003e useDispatch\u003cAppDispatch\u003e();\nexport const useAppSelector: TypedUseSelectorHook\u003cRootState\u003e = useSelector;\n\nexport const fetchSubject =\n  (id: any): AppThunk =\u003e\n  async dispatch =\u003e {\n    const timeoutPromise = (timeout: number) =\u003e new Promise(resolve =\u003e setTimeout(resolve, timeout));\n\n    await timeoutPromise(200);\n\n    dispatch(\n      subjectSlice.actions.setEnt({\n        [id]: {\n          id,\n          name: `Subject ${id}`,\n        },\n      }),\n    );\n  };\n\nexport const wrapper = createWrapper\u003cAppStore\u003e(makeStore);\n\nexport const selectSubject = (id: any) =\u003e (state: AppState) =\u003e state?.[subjectSlice.name]?.[id];\n```\n\nIt is recommended to export typed `State` and `ThunkAction`:\n\n```ts\nexport type AppStore = ReturnType\u003ctypeof makeStore\u003e;\nexport type AppState = ReturnType\u003cAppStore['getState']\u003e;\nexport type AppThunk\u003cReturnType = void\u003e = ThunkAction\u003cReturnType, AppState, unknown, Action\u003e;\n```\n\n### Server and Client state separation\n\nEach time when pages that have `getStaticProps` or `getServerSideProps` are opened by user the `HYDRATE` action will be dispatched. The `payload` of this action will contain the `state` at the moment of static generation or server side rendering, so your reducer must merge it with existing client state properly.\n\nThe easiest and most stable way to make sure nothing is accidentally overwritten is to make sure that your reducer applies client side and server side actions to different substates of your state and they never clash:\n\n```typescript\nexport interface State {\n  server: any;\n  client: any;\n}\n\nconst reducer = (state: State = {tick: 'init'}, action: AnyAction) =\u003e {\n  switch (action.type) {\n    case HYDRATE:\n      return {\n        ...state,\n        server: {\n          ...state.server,\n          ...action.payload.server,\n        },\n      };\n    case 'SERVER_ACTION':\n      return {\n        ...state,\n        server: {\n          ...state.server,\n          tick: action.payload,\n        },\n      };\n    case 'CLIENT_ACTION':\n      return {\n        ...state,\n        client: {\n          ...state.client,\n          tick: action.payload,\n        },\n      };\n    default:\n      return state;\n  }\n};\n```\n\n\u003cdetails\u003e\n\u003csummary\u003eSame code in JavaScript (without types)\u003c/summary\u003e\n\n```js\nconst reducer = (state = {tick: 'init'}, action) =\u003e {\n  switch (action.type) {\n    case HYDRATE:\n      return {\n        ...state,\n        server: {\n          ...state.server,\n          ...action.payload.server,\n        },\n      };\n    case 'SERVER_ACTION':\n      return {\n        ...state,\n        server: {\n          ...state.server,\n          tick: action.payload,\n        },\n      };\n    case 'CLIENT_ACTION':\n      return {\n        ...state,\n        client: {\n          ...state.client,\n          tick: action.payload,\n        },\n      };\n    default:\n      return state;\n  }\n};\n```\n\n\u003c/details\u003e\n\nIf you prefer an isomorphic approach for some (preferably small) portions of your state, you can share them between client and server on server-rendered pages using [next-redux-cookie-wrapper](https://github.com/bjoluc/next-redux-cookie-wrapper), an extension to next-redux-wrapper.\nIn this case, for selected substates, the server is aware of the client's state (unless in `getStaticProps`) and there is no need to separate server and client state.\n\nAlso, you can use a library like https://github.com/benjamine/jsondiffpatch to analyze diff and apply it properly.\n\n### Document\n\nI don't recommend using `withRedux` in `pages/_document.js`, Next.JS [does not provide](https://github.com/zeit/next.js/issues/1267)\na reliable way to determine the sequence when components will be rendered. So per Next.JS recommendation it is better\nto have just data-agnostic things in `pages/_document`.\n\n### Error Pages\n\nError pages can also be wrapped the same way as any other pages.\n\nTransition to an error page (`pages/_error.js` template) will cause `pages/_app.js` to be applied but it is always a\nfull page transition (not HTML5 pushState), so client will have the store created from scratch using state from the server.\nSo unless you persist the store on the client somehow the resulting previous client state will be ignored.\n\n### Async actions\n\nYou can use https://github.com/reduxjs/redux-thunk to dispatch async actions:\n\n```js\nfunction someAsyncAction(id) {\n  return async function (dispatch, getState) {\n    return someApiCall(id).then(res =\u003e {\n      dispatch({\n        type: 'FOO',\n        payload: res,\n      });\n    });\n  };\n}\n\n// usage\nawait store.dispatch(someAsyncAction());\n```\n\nYou can also install https://github.com/pburtchaell/redux-promise-middleware in order to dispatch Promises as async actions. Follow the installation guide of the library, then you'll be able to handle it like this:\n\n```js\nfunction someAsyncAction() {\n  return {\n    type: 'FOO',\n    payload: new Promise(resolve =\u003e resolve('foo')),\n  };\n}\n\n// usage\nawait store.dispatch(someAsyncAction());\n```\n\n### Custom serialization and deserialization\n\nIf you are storing complex types such as Immutable.JS or JSON objects in your state, a custom serialize and deserialize\nhandler might be handy to serialize the redux state on the server and deserialize it again on the client. To do so,\nprovide `serializeState` and `deserializeState` as config options to `withRedux`.\n\nThe reason is that state snapshot is transferred over the network from server to client as a plain object.\n\nExample of a custom serialization of an Immutable.JS state using `json-immutable`:\n\n```js\nconst {serialize, deserialize} = require('json-immutable');\n\ncreateWrapper({\n  serializeState: state =\u003e serialize(state),\n  deserializeState: state =\u003e deserialize(state),\n});\n```\n\nSame thing using Immutable.JS:\n\n```js\nconst {fromJS} = require('immutable');\n\ncreateWrapper({\n  serializeState: state =\u003e state.toJS(),\n  deserializeState: state =\u003e fromJS(state),\n});\n```\n\n### Usage with Redux Saga\n\n[Note, this method _may_ be unsafe - make sure you put a lot of thought into handling async sagas correctly. Race conditions happen very easily if you aren't careful.] To utilize Redux Saga, one simply has to make some changes to their `makeStore` function. Specifically, `redux-saga` needs to be initialized inside this function, rather than outside of it. (I did this at first, and got a nasty error telling me `Before running a Saga, you must mount the Saga middleware on the Store using applyMiddleware`). Here is how one accomplishes just that. This is just slightly modified from the setup example at the beginning of the docs. Keep in mind that this setup will opt you out of Automatic Static Optimization: https://err.sh/next.js/opt-out-auto-static-optimization.\n\nCreate your root saga as usual, then implement the store creator:\n\n```typescript\nimport {createStore, applyMiddleware, Store} from 'redux';\nimport {createWrapper, Context} from 'next-redux-wrapper';\nimport createSagaMiddleware, {Task} from 'redux-saga';\nimport reducer, {State} from './reducer';\nimport rootSaga from './saga';\n\nexport interface SagaStore extends Store {\n  sagaTask?: Task;\n}\n\nexport const makeStore = (context: Context) =\u003e {\n  // 1: Create the middleware\n  const sagaMiddleware = createSagaMiddleware();\n\n  // 2: Add an extra parameter for applying middleware:\n  const store = createStore(reducer, applyMiddleware(sagaMiddleware));\n\n  // 3: Run your sagas on server\n  (store as SagaStore).sagaTask = sagaMiddleware.run(rootSaga);\n\n  // 4: now return the store:\n  return store;\n};\n\nexport const wrapper = createWrapper\u003cStore\u003cState\u003e\u003e(makeStore, {debug: true});\n```\n\n\u003cdetails\u003e\n\u003csummary\u003eSame code in JavaScript (without types)\u003c/summary\u003e\n\n```js\nimport {createStore, applyMiddleware} from 'redux';\nimport {createWrapper} from 'next-redux-wrapper';\nimport createSagaMiddleware from 'redux-saga';\nimport reducer from './reducer';\nimport rootSaga from './saga';\n\nexport const makeStore = context =\u003e {\n  // 1: Create the middleware\n  const sagaMiddleware = createSagaMiddleware();\n\n  // 2: Add an extra parameter for applying middleware:\n  const store = createStore(reducer, applyMiddleware(sagaMiddleware));\n\n  // 3: Run your sagas on server\n  store.sagaTask = sagaMiddleware.run(rootSaga);\n\n  // 4: now return the store:\n  return store;\n};\n\nexport const wrapper = createWrapper(makeStore, {debug: true});\n```\n\n\u003c/details\u003e\n\n#### Using `pages/_app`\n\nThen in the `pages/_app` wait stop saga and wait for it to finish when execution is on server:\n\n```tsx\nimport React from 'react';\nimport App, {AppInitialProps} from 'next/app';\nimport {END} from 'redux-saga';\nimport {SagaStore, wrapper} from '../components/store';\n\nclass WrappedApp extends App\u003cAppInitialProps\u003e {\n  public static getInitialProps = wrapper.getInitialAppProps(store =\u003e async context =\u003e {\n    // 1. Wait for all page actions to dispatch\n    const pageProps = {\n      // https://nextjs.org/docs/advanced-features/custom-app#caveats\n      ...(await App.getInitialProps(context)).pageProps,\n    };\n\n    // 2. Stop the saga if on server\n    if (context.ctx.req) {\n      store.dispatch(END);\n      await (store as SagaStore).sagaTask.toPromise();\n    }\n\n    // 3. Return props\n    return {pageProps};\n  });\n\n  public render() {\n    const {Component, pageProps} = this.props;\n    return \u003cComponent {...pageProps} /\u003e;\n  }\n}\n\nexport default wrapper.withRedux(WrappedApp);\n```\n\n\u003cdetails\u003e\n\u003csummary\u003eSame code in JavaScript (without types)\u003c/summary\u003e\n\n```js\nimport React from 'react';\nimport App from 'next/app';\nimport {END} from 'redux-saga';\nimport {SagaStore, wrapper} from '../components/store';\n\nclass WrappedApp extends App {\n    static getInitialProps = wrapper.getInitialAppProps(store =\u003e async context =\u003e {\n        // 1. Wait for all page actions to dispatch\n        const pageProps = {\n            // https://nextjs.org/docs/advanced-features/custom-app#caveats\n            ...(await App.getInitialProps(context)).pageProps,\n        };\n\n        // 2. Stop the saga if on server\n        if (context.ctx.req) {\n            store.dispatch(END);\n            await store.sagaTask.toPromise();\n        }\n\n        // 3. Return props\n        return {pageProps};\n    });\n\n    public render() {\n        const {Component, pageProps} = this.props;\n        return \u003cComponent {...pageProps} /\u003e;\n    }\n}\n\nexport default wrapper.withRedux(WrappedApp);\n```\n\n\u003c/details\u003e\n\n#### Using `getServerSideProps` or `getStaticProps`\n\nIn order to use it with `getServerSideProps` or `getStaticProps` you need to `await` for sagas in each page's handler:\n\n```js\nexport const getServerSideProps = ReduxWrapper.getServerSideProps(async ({store, req, res, ...etc}) =\u003e {\n  // regular stuff\n  store.dispatch(ApplicationSlice.actions.updateConfiguration());\n  // end the saga\n  store.dispatch(END);\n  await store.sagaTask.toPromise();\n});\n```\n\n#### Usage without `getInitialProps` inside `_app`\n\nIf you don't want to opt-out of automatic pre-rendering in your Next.js app, you can manage server-called sagas on a per page basis like [the official Next.js \"with Redux Saga\" example](https://github.com/vercel/next.js/tree/canary/examples/with-redux-saga) does. If you do go with this option, please ensure that you await any and all sagas within any [Next.js page methods](https://nextjs.org/docs/basic-features/data-fetching). If you miss it on one of pages you'll end up with inconsistent state being sent to client. So, we consider waiting in `_app` to be automatically safer, but obviously the main drawback is opting out of automatic static exports.\n\n### Usage with Redux Persist\n\n\u003e If you only need to persist small portions of your state, [next-redux-cookie-wrapper](https://github.com/bjoluc/next-redux-cookie-wrapper) might be an easy alternative to Redux Persist that supports SSR.\n\nBoilerplate: https://github.com/fazlulkarimweb/with-next-redux-wrapper-redux-persist\n\nHonestly, I think that putting a persistence gate is not necessary because the server can already send _some_ HTML with\n_some_ state, so it's better to show it right away and then wait for `REHYDRATE` action to happen to show additional\ndelta coming from persistence storage. That's why we use Server Side Rendering in the first place.\n\nBut, for those who actually want to block the UI while rehydration is happening, here is the solution (still hacky though):\n\n```js\n// lib/redux.js\nimport logger from 'redux-logger';\nimport {applyMiddleware, createStore} from 'redux';\n\nconst SET_CLIENT_STATE = 'SET_CLIENT_STATE';\n\nexport const reducer = (state, {type, payload}) =\u003e {\n  // Usual stuff with HYDRATE handler\n  if (type === SET_CLIENT_STATE) {\n    return {\n      ...state,\n      fromClient: payload,\n    };\n  }\n  return state;\n};\n\nconst makeConfiguredStore = reducer =\u003e createStore(reducer, undefined, applyMiddleware(logger));\n\nconst makeStore = () =\u003e {\n  const isServer = typeof window === 'undefined';\n\n  if (isServer) {\n    return makeConfiguredStore(reducer);\n  } else {\n    // we need it only on client side\n    const {persistStore, persistReducer} = require('redux-persist');\n    const storage = require('redux-persist/lib/storage').default;\n\n    const persistConfig = {\n      key: 'nextjs',\n      whitelist: ['fromClient'], // make sure it does not clash with server keys\n      storage,\n    };\n\n    const persistedReducer = persistReducer(persistConfig, reducer);\n    const store = makeConfiguredStore(persistedReducer);\n\n    store.__persistor = persistStore(store); // Nasty hack\n\n    return store;\n  }\n};\n\nexport const wrapper = createWrapper(makeStore);\n\nexport const setClientState = clientState =\u003e ({\n  type: SET_CLIENT_STATE,\n  payload: clientState,\n});\n```\n\nAnd then in Next.js `_app` page you can use bare context access to get the store (https://react-redux.js.org/api/provider#props):\n\n```js\n// pages/_app.tsx\nimport React from 'react';\nimport App from 'next/app';\nimport {ReactReduxContext} from 'react-redux';\nimport {wrapper} from './lib/redux';\nimport {PersistGate} from 'redux-persist/integration/react';\n\nexport default wrapper.withRedux(\n  class MyApp extends App {\n    render() {\n      const {Component, pageProps} = this.props;\n      return (\n        \u003cReactReduxContext.Consumer\u003e\n          {({store}) =\u003e (\n            \u003cPersistGate persistor={store.__persistor} loading={\u003cdiv\u003eLoading\u003c/div\u003e}\u003e\n              \u003cComponent {...pageProps} /\u003e\n            \u003c/PersistGate\u003e\n          )}\n        \u003c/ReactReduxContext.Consumer\u003e\n      );\n    }\n  },\n);\n```\n\nOr using hooks:\n\n```js\n// pages/_app.tsx\nimport React from 'react';\nimport App from 'next/app';\nimport {useStore} from 'react-redux';\nimport {wrapper} from './lib/redux';\nimport {PersistGate} from 'redux-persist/integration/react';\n\nexport default wrapper.withRedux(({Component, pageProps}) =\u003e {\n  const store = useStore();\n  return (\n    \u003cPersistGate persistor={store.__persistor} loading={\u003cdiv\u003eLoading\u003c/div\u003e}\u003e\n      \u003cComponent {...pageProps} /\u003e\n    \u003c/PersistGate\u003e\n  );\n});\n```\n\nAnd then in Next.js page:\n\n```js\n// pages/index.js\nimport React from 'react';\nimport {connect} from 'react-redux';\n\nexport default connect(state =\u003e state, {setClientState})(({fromServer, fromClient, setClientState}) =\u003e (\n  \u003cdiv\u003e\n    \u003cdiv\u003efromServer: {fromServer}\u003c/div\u003e\n    \u003cdiv\u003efromClient: {fromClient}\u003c/div\u003e\n    \u003cdiv\u003e\n      \u003cbutton onClick={e =\u003e setClientState('bar')}\u003eSet Client State\u003c/button\u003e\n    \u003c/div\u003e\n  \u003c/div\u003e\n));\n```\n\n## Upgrade from 6.x to 7.x\n\n1. Signature of `createWrapper` has changed: instead of `createWrapper\u003cState\u003e` you should use `createWrapper\u003cStore\u003cState\u003e\u003e`, all types will be automatically inferred from `Store`.\n\n2. `GetServerSidePropsContext` and `GetStaticPropsContext` are no longer exported from `next-redux-wrapper`, you should use `GetServerSideProps`, `GetServerSidePropsContext`, `GetStaticProps` and `GetStaticPropsContext` directly from `next`.\n\n3. All signatures like `({store, req, res, ...}) =\u003e { ... }` were changed to `store =\u003e ({req, res, ...}) =\u003e { ... }` in order to keep Next.js internals free of modifications and for better typings support.\n\n4. In version `7.x` you have to manually wrap all `getInitialProps` with proper wrappers: `wrapper.getInitialPageProps` and `wrapper.getInitialAppProps`.\n\n5. **window.NEXT_REDUX_WRAPPER_STORE** has been removed as it was causing [issues with hot reloading](https://github.com/kirill-konshin/next-redux-wrapper/pull/324)\n\n## Upgrade from 5.x to 6.x\n\nMajor change in the way how things are wrapped in version 6.\n\n1. Default export `withRedux` is marked deprecated, you should create a wrapper `const wrapper = createWrapper(makeStore, {debug: true})` and then use `wrapper.withRedux(MyApp)`.\n\n2. Your `makeStore` function no longer gets `initialState`, it only receives the context: `makeStore(context: Context)`. Context could be [`NextPageContext`](https://nextjs.org/docs/api-reference/data-fetching/getInitialProps) or [`AppContext`](https://nextjs.org/docs/advanced-features/custom-app) or [`getStaticProps`](https://nextjs.org/docs/basic-features/data-fetching#getstaticprops-static-generation) or [`getServerSideProps`](https://nextjs.org/docs/basic-features/data-fetching#getserversideprops-server-side-rendering) context depending on which lifecycle function you will wrap. Instead, you need to handle the `HYDRATE` action in the reducer. The `payload` of this action will contain the `state` at the moment of static generation or server side rendering, so your reducer must merge it with existing client state properly.\n\n3. `App` should no longer wrap its children with `Provider`, it is now done internally.\n\n4. `isServer` is not passed in `context`/`props`, use your own function or simple check `const isServer = typeof window === 'undefined'` or `!!context.req` or `!!context.ctx.req`.\n\n5. `store` is not passed to wrapped component props.\n\n6. `WrappedAppProps` was renamed to `WrapperProps`.\n\n## Upgrade from 1.x to 2.x\n\nIf your project was using Next.js 5 and Next Redux Wrapper 1.x these instructions will help you to upgrade to 2.x.\n\n1. Upgrade Next.js and Wrapper\n\n   ```bash\n   $ npm install next@6 --save-dev\n   $ npm install next-redux-wrapper@latest --save\n   ```\n\n2. Replace all usages of `import withRedux from \"next-redux-wrapper\";` and `withRedux(...)(WrappedComponent)` in all\n   your pages with plain React Redux `connect` HOC:\n\n   ```js\n   import {connect} from \"react-redux\";\n\n   export default connect(...)(WrappedComponent);\n   ```\n\n   You also may have to reformat your wrapper object-based config to simple React Redux config.\n\n3. Create the `pages/_app.js` file with the following minimal code:\n\n   ```js\n   // pages/_app.js\n   import React from 'react'\n   import {Provider} from 'react-redux';\n   import App from 'next/app';\n   import {wrapper} from '../store';\n\n   class MyApp extends App {\n       static async getInitialProps = (context) =\u003e ({\n           pageProps: {\n               // https://nextjs.org/docs/advanced-features/custom-app#caveats\n               ...(await App.getInitialProps(context)).pageProps,\n           }\n       });\n\n       render() {\n           const {Component, pageProps} = this.props;\n           return (\n               \u003cComponent {...pageProps} /\u003e\n           );\n       }\n\n   }\n\n   export default wrapper.withRedux(MyApp);\n   ```\n\n4. Follow [Next.js 6 upgrade instructions](https://github.com/zeit/next.js/issues/4239) for all your components\n   (`props.router` instead of `props.url` and so on)\n\nThat's it. Your project should now work the same as before.\n\n## Resources\n\n- [next-redux-saga](https://github.com/bmealhouse/next-redux-saga)\n- [How to use with Redux and Redux Saga](https://www.robinwieruch.de/nextjs-redux-saga/)\n- Redux Saga Example: https://gist.github.com/pesakitan22/94b4984140ba0f2c9e52c5289a7d833e.\n- [next-redux-cookie-wrapper](https://github.com/bjoluc/next-redux-cookie-wrapper)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkirill-konshin%2Fnext-redux-wrapper","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkirill-konshin%2Fnext-redux-wrapper","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkirill-konshin%2Fnext-redux-wrapper/lists"}