'Redux Toolkit: How can I store a serialized action creator in state?
Question
I am using Redux Toolkit and I want to store an action creator in state. When I do this, I receive an error regarding non-serializable values in my action as well as my state. Using the code below as an example of my issue, how can I resolve it without just suppressing the warning?
Slice Code
import { ActionCreatorWithoutPayload } from '@reduxjs/toolkit';
export type ModalType =
{
type: 'MyModal';
actionText: string;
onConfirm: ActionCreatorWithoutPayload;
}
type ui = {
modal: ModalType | null;
};
const initialState: ui = {
modal: null
};
export const slice = createSlice({
name: 'ui',
initialState: initialState,
reducers: {
showDialog: (state, action: PayloadAction<ModalType>) => {
state.modal= action.payload;
},
someAction: (state) => {
// do something
},
}
});
Component Code
import { someAction } from 'reducers/uiSlice';
<Button
onClick={() =>
dispatch(
showDialog({
type: 'MyModal', actionText: `Some text`, onConfirm: someAction}
)
)}
/>
Error Message
A non-serializable value was detected in an action, in the state: `payload.onConfirm`. Value: ƒ actionCreator() {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
if (prepareAction) {
var prepared = prepareAction.apply(void…
Solution 1:[1]
To be honest, this is a bad idea, and really not at all how Redux should be used.
Based on the examples, it looks like you're trying to create a modal and pass in a callback as a prop. There are other ways to do this that will work better with Redux, and in fact a few years ago I wrote a post on Managing Modals and Context Menus with Redux. It shows a few different techniques to do this in a way that is compatible with how Redux should be used.
Today, the option I'd recommend is using a custom middleware that tracks what modals are open, returns a promise from dispatch(showModal()), and resolves the promise when you do dispatch(closeModal(modalId)).
The post links to https://github.com/AKolodeev/redux-promising-modals as one option for this. I also have an incomplete but mostly working similar implementation in a gist at https://gist.github.com/markerikson/8cd881db21a7d2a2011de9e317007580 that shows some of the potential approaches.
Solution 2:[2]
You can disable the SerializableCheck like below
import {getDefaultMiddleware} from "@reduxjs/toolkit";
const customMiddleWare = getDefaultMiddleware({
serializableCheck: false,
});
export default configureStore({
reducer: {
...your reducers
},
middleware: customMiddleWare,
});
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | markerikson |
| Solution 2 | Johndev247 |
