skip to Main Content

I’m building an e-commerce app with Next.js and redux. I have noticed that when I add redux-persist to the app all meta tags stop working. I have added my code snippets below

import { combineReducers } from 'redux'
import { configureStore } from '@reduxjs/toolkit'
import shopReducer from './reducers/shop/shopSlice'
import storage from 'redux-persist/lib/storage'
import { persistStore,persistReducer, FLUSH, REHYDRATE, PAUSE, PERSIST, PURGE, REGISTER } from 'redux-persist'

const initState = {}

const persistConfig = {
   key: 'root',
   version: 1,
   storage,
   whitelist: ['shop'],
}

const rootReducer = combineReducers({
   shop: shopReducer,
})

const persistedReducer = persistReducer(persistConfig, rootReducer)

const reduxStore = () => {
   const store = configureStore ({
       initState,
       reducer: persistedReducer,
       middleware: (getDefaultMiddleware) =>
       getDefaultMiddleware({
          serializableCheck: {
             ignoredActions: [FLUSH, REHYDRATE, PAUSE, PERSIST, PURGE, REGISTER],
          },
       }),
   })

   const persistor = persistStore(store)
   return { persistor, store }
}

export default reduxStore

Then in _app.js

import Layout from '../components/Layout'
import { Provider } from 'react-redux'
import reduxStore from '../context/store'
import { PersistGate } from 'redux-persist/integration/react'

const { persistor, store } = reduxStore()

function MyApp({ Component, pageProps }){
    return (
        <Provider store={store}>
            <PersistGate loading={null} persistor={persistor}>
                <Layout>
                    <Component {...pageProps} />
                </Layout>
            </PersistGate>
        </Provider>
    )
}

export default MyApp

The meta tags component is like this excluding the other tags.

import Head from 'next/head'

function Meta({ title, keywords, description, image, appName, url }){
    return (
        <Head>
            <meta name="theme-color" content="#0066b2" />
            <meta name="description" content={description} />
            <meta name="keywords" content={keywords} />
            <meta name="author" content="author" />
            <meta name="twitter:card" content="summary_large_image" />
            <meta name="twitter:title" content={title} />
            <meta name="twitter:description" content={description} />
            <meta property="twitter:image" content={image} />
            <meta property="twitter:image:alt" content={appName} />
            <meta name="msapplication-TileColor" content="#ffffff" />
            <title>{title}</title>
        </Head>
    )
}

Meta.defaultProps = {
    appName: 'Store',
    url: 'https://example.com',
    title: 'Store Example',
    keywords: 'ecommerce',
    description: 'Store',
    image: '/storefront.png',
}

export default Meta

How can I fix the issue because I want to use both – redux-persist to save a guest shopping cart and meta tags for SEO?

Thanks

2

Answers


  1. Chosen as BEST ANSWER

    I've found a solution on this Github link. Apparently there's an issue with redux-persist which disables SSR and that's basically why meta tags don't work when using redux-persist.

    The solution is to change the code below

    <PersistGate persistor={persistor} loading={null}>
        <Layout>
            <Component {...pageProps} />
        </Layout>
    </PersistGate>
    

    to this

    <PersistGate persistor={persistor} loading={null}>
        {() => (
            <Layout>
                <Component {...pageProps} />
            </Layout>
        )}
    </PersistGate>
    

  2. In case anyone is still facing this same error, here’s another solution to this.

    This issue with the initial solution is UI Rehydration problem would occur frequently on SSG pages, see why (https://nextjs.org/docs/messages/react-hydration-error)

    const PersistGateComponent = dynamic(
      () =>
        import('redux-persist/integration/react').then((mod) => mod.PersistGate),
      {
        ssr: false,
      }
    );
    
    const SSROutset = ({ children, persistor }) => {
      if (typeof window !== 'undefined') {
        return (
          <PersistGateComponent
            persistor={persistor}
          >
            {children}
          </PersistGateComponent>
        );
      }
    
      // You can create a visually hidden component to avoid layout flashes and also maintain SEO content
      // see Chakra for an example of one https://chakra-ui.com/docs/components/visually-hidden
      return <VisuallyHidden>{children}</VisuallyHidden>;
    };
    

    Usage

       <Provider store={store}>
        <SSROutset persistor={store.__persistor}>
          <Component .... />
        </SSROutset>
       </Provider>
    

    Please let me know if this resolves your issue. With this solution, rehydration challenges are effectively addressed, ensuring that your states are consistently bootstrapped and persisted in the correct manner.

    NB: this is also with the next-redux-wrapper implementation.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search