React Redux Toolkit: How can I can store my initialState to localStorage using createSlice?

Viewed 5820

I'm a bit too confused about how can I Store the initialState of my taskSlice into my localStorage. Can you please help me with how can I solve this problem? The result that I want is if the app runs the initialState will be store in the localStorage. Coz what I'm doing is using useSelector inside my component then useEffect to know if there's an existing localStorage value. If false it will store the state inside the localStorage.

taskSlice.js

import { createSlice } from '@reduxjs/toolkit';
import { v4 as uuidv4 } from 'uuid';

const initialState = [
  {
    _id: uuidv4(),
    title: 'Learn React',
    desc: 'Nec ullamcorper sit amet risus nullam eget felis.',
    isProgress: false,
    isComplete: false,
    priority: 'Minor',
    created: 'johndoe',
    assigned: 'Doe John',
    dateCreated: new Date(),
    dateDue: new Date(),
  },
];

export const taskSlice = createSlice({
  name: 'tasks',
  initialState: initialState,
  reducers: {
addTodo: (state, action) => {
      state.push({
        _id: uuidv4(),
        title: action.payload.taskInfo.title,
        desc: action.payload.taskInfo.description,
        isProgress: false,
        isComplete: false,
        priority: action.payload.taskInfo.priority,
        dateCreated: new Date(),
        created: action.payload.taskInfo.created,
        assigned: action.payload.taskInfo.assigned,
        dateDue: action.payload.taskInfo.dateDue,
      });
    },
  },
});

export const { addTodo } = taskSlice.actions;

export const taskSelector = (state) => state.tasks;

export default taskSlice.reducer;
1 Answers
  1. First add a hydrate action
export const taskSlice = createSlice({
  name: 'tasks',
  initialState: initialState,
  reducers: {
hydrate:(state, action) => {
// do not do state = action.payload it will not update the store
return action.payload
},
addTodo: (state, action) => {
      state.push({
        _id: uuidv4(),
        title: action.payload.taskInfo.title,
        desc: action.payload.taskInfo.description,
        isProgress: false,
        isComplete: false,
        priority: action.payload.taskInfo.priority,
        dateCreated: new Date(),
        created: action.payload.taskInfo.created,
        assigned: action.payload.taskInfo.assigned,
        dateDue: action.payload.taskInfo.dateDue,
      });
    },
  },
});
  1. Save state on store refresh
store.subscribe(()=>{
  localStorage.setItem('reduxState', JSON.stringify(store.getState()))
})
  1. Before giving the store to provider lookup into localstorage if there are todos there dispatch hydrate action with payload.It is wise to do as so rather than using it in a functional component as it is simple to reason about.
const getTodosFromLocalStorage = () => {
  try { 
    const persistedState = localStorage.getItem('reduxState') 
    if (persistedState) 
      return JSON.parse(persistedState)
  }
  catch (e){ 
    console.log(e)
  }
}

const todos = getTodosFromLocalStorage()
if(todos){
  store.dispatch(hydrate(todos))
}
// All safe give it to Provider
ReactDOM.render(
  <React.StrictMode>
        <Provider store={store}>
            <App />
        </Provider>    
  </React.StrictMode>,
  document.getElementById('root')
)
Related