Can a redux-toolkit createSlice use a js Map as state?

Viewed 4309

In general, using a mutable object such as Map is strongly discouraged.

However, the magic of immer allows immutable objects to be manipulated as though they are mutable.

Specifically, immer supports immutable versions of Map using enableMapSet

In redux-toolkit createReducer and createSlice wrap state manipulation with immer's produce.

Collectively, I think these facts mean code like this should be safe:

import { createSlice } from '@reduxjs/toolkit'

export const testmapSlice = createSlice({
  name: 'testMap',
  // Using a Map() as redux state
  initialState: new Map(),
  reducers: {
    add: (state, action) => {
      state.set(action.payload.identity, action.payload)
    },
  },
})

However, when I use this in a React component, I get the polite error message A non-serializable value was detected in the state, in the path: `testMap`. Value: Map(1) {"A" => {…}} Take a look at the reducer(s) handling this action type: testMap/add..

Is there a way to safely use Map without getting this error message?

2 Answers

Define "safely" :)

In theory, you could put anything you want into the Redux store.

In practice, per that FAQ, non-serializable values are likely to cause things like the DevTools to break (which defeats much of the purpose of using Redux in the first place). Use of Maps and other mutable instances are also likely to cause portions of your UI to not re-render correctly, because React-Redux relies on reference checks to determine if data has changed. So, we specifically tell users that you should never put non-serializable values in the Redux state.

In this particular case, you should be able to use a plain JS object as a lookup table rather than a Map, and accomplish the same behavior.

As an absolute last resort, you can turn off the serialization checking for certain parts of the state, but we strongly discourage folks from doing that.

I think it is not safe to use Map() on the state because Redux is already designed to avoid the mutation at the level of Reducers, and when you use createSlice() it even takes care of it in the background. Your idea of a double security at the State level may appear to be another issue that you provoke. It might either provoke the UI not to update. or throw an error (Ps: This is purely analogic. I have not tried it)

Related