Redux-toolkit: Incorrect detection of non-serialisable values?

Created on 23 May 2021  路  3Comments  路  Source: reduxjs/redux-toolkit

Hi everyone, I've found an issue in my project:

I switched to redux-toolkit to get the typings right for the project, but started getting errors that my state was not serialisable: fair enough, I made functions to reduce all my classes to bare object representations which implement the three interfaces as follows:

export interface ProjectEntity {
  id: string;
  emoji: string;
  name: string;
  notes: string;
  completed: boolean;
  deadlines: DeadlineEntity[];
  todos: TodoEntity[];
}

export interface TodoEntity {
  id: string;
  emoji: string;
  name: string;
  project: string;
  deadline?: string;
  laps: number;
  completed: boolean;
  remaining?: number;
  finishingTime?: number;
};

export interface DeadlineEntity {
  id: string;
  name: string;
  due: number;
  todos: string[];
}

Despite this, I still get errors in my project when pulling the Array of ProjectEntity from firebase:

A non-serializable value was detected in an action, in the path: payload.0.todos. Value: []
Take a look at the logic that dispatched this action: {"payload": [{"completed": false, "deadlines": [List], "emoji": "馃憖", "id": "7af97a8d-0f65-46e2-820d-2b18f154aaa7", "name": "Sage", "notes": "", "todos": [List]}, {"completed": true, "deadlines": [List], "emoji": "馃搶", "id": "d5e8584e-ff2c-4df3-baf9-06a381be3ab2", "name": "Business Strategy", "notes": "", "todos": [List]}], "type": "PROJECT_HYDRATE"}

Additionally, even before loading values from firebase, the default empty project still logs the same error:

A non-serializable value was detected in an action, in the path: payload.0.todos. Value: []

After searching on the redux-toolkit docs, I stumbled upon this page, which prompted me to use the documented functions to write tests to check that my data is indeed serialisable:

test("Object serialisability checks", () => {
  expect(isPlainObject(project1a.toEntity())).toEqual(true);
  expect(isPlain([project1a.toEntity(), project1b.toEntity()])).toEqual(true);
});

The test above passes, but I still get errors regardless. I've also tried running similar console.log-style tests during program execution on the incoming data from firebase, and isPlain returns true for the exact same value that produces the log error. Is there something I'm missing, or is this intended behaviour?

All 3 comments

Can you put together a CodeSandbox that shows this issue? Hard to give an exact response without seeing _exactly_ what the values are at runtime.

I was putting the sandbox together, and found what I was missing. In fact, it's right in the dump above: I was using Immutable.js Lists for some processing operations, and forgot to call .toArray() at the end of one of the conversions. I didn't think to look here, since I was expecting the type system to scream at me, but as it turns out, Immutable.js Lists are acceptable as Arrays.

I'm so sorry if this was a waste of your time. Thanks anyway for the quick response, huge fan of your blog posts! Your post on the react render cycle taught me things I never would have even thought to consider!

Yeah, I thought I kinda saw a couple List entries nested down in there, but I was a bit confused because it didn't say a path like payload.0.todos.3 or something.

FWIW, today we recommend _not_ using Immutable.js with Redux - there's not enough benefit, and Immer is much simpler anyway and solves most of the same problems anyway.

And thanks, glad that post was helpful! :)

Was this page helpful?
0 / 5 - 0 ratings