Search code examples
javascriptreactjsreact-reduxredux-toolkitrtk-query

How to persist dark mode in Redux state


I wrote a theme changer using Redux-Toolkit (RTK) Query, but I can't manage to find a way to make the page persist in the same theme it was before refreshing it.

Here's the code:

import { createSlice } from "@reduxjs/toolkit";

export const themeSlice = createSlice({
  name: "themeSlice",
  initialState: true, // Initial value is light theme
  reducers: {
    toggleTheme: (state) =>{
      return state = !state; // Changes the theme to dark
    }
  }
});

export const { toggleTheme } = themeSlice.actions
export default themeSlice.reducer;

Redux Store:

import { configureStore } from "@reduxjs/toolkit";

export const store = configureStore({
  reducer: {
    theme: themeReducer,
  },
})

I personally want to save the theme name in the localStorage. I tried several tutorials, but none worked.


Solution

  • A trivial solution would be to locally set the initial state value from localStorage and persist the state changes to localStorage.

    Example:

    // Read initial state value from localStorage or provide 
    // default fallback value
    const initialState = JSON.parse(localStorage.getItem("theme")) ?? true;
    
    export const themeSlice = createSlice({
      name: "themeSlice",
      initialState,
      reducers: {
        toggleTheme: (state) => {
          // Compute the next state
          const nextState = !state;
    
          // Persist the next state value
          localStorage.setItem("theme", JSON.stringify(nextState));
    
          // Return the next state value
          return nextState;
        }
      }
    });
    

    Edit how-to-persist-dark-mode-in-redux-state

    Reducer functions are supposed to be pure functions, e.g. free of side-effects, so the above solution may be frowned-upon. Redux-Persist is a common and popular library solution for persisting and hydrating a Redux store. If you are fairly familiar with Redux already then it is about a 5-15 minute integration.

    Basic example:

    import { configureStore, combineReducers } from "@reduxjs/toolkit";
    import { persistStore, persistReducer } from "redux-persist";
    import storage from "redux-persist/lib/storage";
    
    const persistConfig = {
      key: 'root',
      storage,
    };
    
    const rootReducer = combineReducers({
      theme: themeReducer,
    });
    
    const persistedReducer = persistReducer(persistConfig, rootReducer)
    
    export const store = configureStore({
      reducer: persistedReducer,
    });
    
    export const persistor = persistStore(store);
    
    import { Provider } from "react-redux";
    import { PersistGate } from "redux-persist/integration/react";
    import { store, persistor } from "../path/to/store";
    
    ...
    
    <Provider store={store}>
      <PersistGate loading={null} persistor={persistor}>
        <App />
      </PersistGate>
    </Provider>
    

    Edit how-to-persist-dark-mode-in-redux-state (redux-persist)