I recently was trying to convert my app to use the toolkit to avoid all the type boiler plate.
I have Date types in some of my redux state and noticed there was an error/warning in the console about using this. Since Date has a valueOf() and toJSON() I thought it was serializable.
Is there a link to the docs which explains why? Or perhaps I'm seeing the error, but really it's something else?
I could convert all the Date objects pre-emptively to the their string / number value but it seems kind of restrictive.
Error:

middleware checks for all values to serializable
https://github.com/reduxjs/redux-toolkit/blob/a1e8becbb2e4653d721bdc1d2363a45562c526a2/src/serializableStateInvariantMiddleware.ts#L65-L70
it uses isPlain for isSerializable
https://github.com/reduxjs/redux-toolkit/blob/a1e8becbb2e4653d721bdc1d2363a45562c526a2/src/serializableStateInvariantMiddleware.ts#L14-L24
New to the toolkit so maybe I have something configured wrong, but couldn't believe Dates were causing issues and wanted to know why. Thanks.
Generally speaking, anything that requires use of new is a class instance of some kind, and thus we don't consider them to be serializable - only plain objects, arrays, and primitives.
I'm not sure how well the Redux DevTools extension handles Date instances. I'd have to check and see. At the same time, the fact that JSON.parse() can't return a Date instance by default (without use of a reviver function) would also classify them as not serializable.
But yes, I'd typically recommend storing timestamp values as strings or numbers and only converting them into Date or moment instances as needed.
I just finished converting one of our projects to redux toolkit so we're now coming across this issue. We store Date objects quite extensively in our Redux store, and we haven't come across any issues so far. As for why we do this, I've put details below (but made them collapsible since that information is not necessary for my follow-up questions)
Context for why we use
Date objects in our store
We have a lot of deployment stack-specific data for our project. One of the things we do is make our interfaces so that people can select the stack they care about. To do this, we maintain several dictionaries in our redux store that allow us to use an enum of options for stacks to the data associated for those stacks, as well as when that data was refreshed/acquired. These dictionaries are typed like so:
type StackToDataMap = {
[stack in StacksEnum]: {
data: IData[],
refreshed: Date
};
}
In our action creators whenever we make an update to the data for a stack, we just throw in a new Date() to track when we put the information in, like so
refreshDataSuccess(state, action: PayloadAction<IData[]>) {
// typeof stackData === StackToDataMap
state.stackData[state.selectedStack] = {
data: action.payload,
refreshed: new Date()
}
}
We'll use this information to render information for when the data the user was seeing was refreshed/acquired so they know how stale the information they're looking at is.
Some followup questions
I'm not sure how well the Redux DevTools extension handles Date instances
I can confirm that the Redux DevTools extension handles the Dates at least visually. Below is a screenshot of the extension showing the state transition from one of my successful refresh. In my components, the selector always has a proper Date object with right time.

But, I know that I do not know, and doubt this screenshot covers all the things you were probably thinking of when you mentioned the devtools extension. Are there other concerns specific to the Redux Dev Tools extension that would need to be considered?
At the same time, the fact that
JSON.parse()can't return aDateinstance by default (without use of a reviver function) would also classify them as not serializable.
Is this a concern for using toolkit with plain, vanilla JavaScript?
My (potentially silly, naive) question
Would there be a way to turn off this error message for Date objects in the store, at least with Typescript? What other information/scenarios would we need to explore before deciding whether storing a Date in the store would be a bad practice and should warrant the warning?
@markerikson - Please let me know if you think it would be helpful if I created and shared a small project reproducing our behavior of using Date in the store to further explore this.
You can always override the isSerializable option in the serialization check middleware if you want to.
The other reason to avoid putting Date instances into the store is because Dates are inherently mutable. If I do state.someDate.setDay(5), I've mutated it, and there's no evidence that it changes. One of the core principles of Redux is to avoid mutating state. Storing date values as numeric or string timestamps avoids that issue.
Currently I'm trying to figure out if it was possible to use (or build?) a middleware that (de)serializes Date instances using ISO strings or timestamps. Would that be an option?
@newlukai I'm not sure what purpose a middleware would serve here.
If you're storing date values as ISO strings or numeric timestamps, then there's two main cases you need to handle: reading values from state for use in components, and dispatching actions containing new date-related values.
A middleware can't help with reading data, because it's not part of the getState() process. The Redux state will be passed to selectors as-is.
A middleware _could_ hypothetically look at action objects, find any Date instances, and replace them with strings or timestamps, but that's really just about choosing to move some responsibility from the code that dispatches actions over into a central location. I don't see much benefit there.
@markerikson Thanks. And sorry. If I got it right, a middleware is only able to conduct some logic on the way from an action to the reducer. I thought it was also possible to step in on the way from the storage to a selector. Might be totally silly, but I'm quite new to the Redux game :)
@markerikson as a valid use case, consider using OpenApi to fetch data, that is set to a DateTimeOffset in c# and gets turned into a JS Date on the client codegen. If i want to use an almost 1:1 model of the TS generated model ie interface IMyInterface extends MyGeneratedType {date: string} that is returned, i can't (if i don't want dates in my redux store). Having middleware that could auto serialize dates to iso strings would be nice here. Then it's up to the consumer of the store if they want to turn that iso string into a date or not. It would save someone having to write code in their fetch/pre-hydrate step for every entity to serialize. Just a thought
@aleccaputo yeah, there's always edge cases and exceptions, which is why this isn't an absolute hardcoded behavior. As mentioned above, you can override the definition of isSerializable to allow other types, ignore certain actions / state, or even turn off the middleware entirely. But, we want to guide people in the right direction by default.
@markerikson ah, good point. I had misread that comment. I'll dig into that. Thanks!
@markerikson I think that makes sense, and just to clarify for anyone reading this after, the reason why adding middleware to redux would not solve this specific use case is that middleware only touches the data on the way into the store, not on the way out.
If there was a way to add middleware to transform the data after a dispatch and before the data is returned from a useSelector, for example, the you would be able to add custom serialization/deserialization middleware. Currently the value in state is returned directly from the useSelector.
@gregjoeval yeah, exactly. the closest you would get to that is a "store enhancer" ( https://redux.js.org/tutorials/fundamentals/part-4-store#configuring-the-store ) that overrides getState and somehow returns the data, but that itself is awkward - you can't mutate the existing state, and you shouldn't return copies of the state in getState because it'll cause unnecessary re-renders.
Most helpful comment
Generally speaking, anything that requires use of
newis a class instance of some kind, and thus we don't consider them to be serializable - only plain objects, arrays, and primitives.I'm not sure how well the Redux DevTools extension handles
Dateinstances. I'd have to check and see. At the same time, the fact thatJSON.parse()can't return aDateinstance by default (without use of a reviver function) would also classify them as not serializable.But yes, I'd typically recommend storing timestamp values as strings or numbers and only converting them into
Dateormomentinstances as needed.