I am working with material-react-table v3 and this my implementation:
import {MaterialReactTable,useMaterialReactTable} from "material-react-table";
const MaterialTable = ({
columns = [],
data = [],
selectedState,
setSelectedState,
isSelectable = false,
}: any) => {
const table = useMaterialReactTable({
columns,
data,
enableRowSelection: isSelectable,
getRowId: (row) => row.key,
onRowSelectionChange: setSelectedState,
state: { rowSelection: selectedState },
});
return <MaterialReactTable table={table} />;
};
When working with useState hook and passing it as props for rowSelection state and for onRowSelectionChange , everything is working fine .:
const [materialState, setMaterialState] = useState({});
selectedState={materialState}
setSelectedState={setMaterialState}
But I want to use Redux for state management, so I was trying this :
const filters = useSelector((state) => state.filters);
const dispatch = useDispatch();
selectedState={filters.searchTypeSelection}
setSelectedState={(value: any) =>
dispatch(setSearchTypeSelection(value))
}
On this I am getting this error :
A non-serializable value was detected in an action, in the path:
payload. Value: old => {
var _opts$selectChildren;
value = typeof value !== ‘undefined’ ? value : !isSelected;
if (row.getCanSelect() && isSelected === value) {
return old;
… Take a look at the logic that dispatched this action: {type: ‘filters/setSearchTypeSelection’, payload: ƒ} (See
https://redux.js.org/faq/actions#why-should-type-be-a-string-or-at-least-serializable-why-should-my-action-types-be-constants)
(To allow non-serializable values see:
https://redux-toolkit.js.org/usage/usage-guide#working-with-non-serializable-data)
I want to know what is causing this issue and how can I implement state management using redux with material-react-table?
Thank you for your help.
Here is my code example :
https://codesandbox.io/p/devbox/material-react-table-redux-lm6r86
2
Answers
Issue
The basic issue stems from the fact that
setSelectedState
is being passed a function that is passed an updater function.Effectively the
(old: T) => T
signature becauseonRowSelectionChange
is anOnChangeFn
function.src/MaterialTable.jsx
It’s this callback function that is passed as the action payload and is non-serializable. This works with the
materialState
React state because thesetMaterialState
state updater function also has an overloaded function signature, one of which takes the current state value and returns the next state value, e.g.(currentState: T) => T
, and doesn’t care about value serializability.A trivial fix is to simply invoke this function prior to dispatching the
setSearchTypeSelection
action.But this fails to consider any previous/old table state values. While you could manage all this yourself manually within your
setSearchTypeSelection
reducer case it raises a few concerns, but namely duplication of table state logic, e.g. both inMaterialReactTable
and in your reducer logic.Solution Suggestion
I suggest allowing the function to be passed through and invoked in the
setSearchTypeSelection
reducer case, passing the current state value to the callback stored in the action payload. This simply letsMaterialReactTable
handle the update logic.src/filtersSlice.js
Now this just leaves the Redux serializability issue, which is trivially addressed by configuring the serializability check to ignore the
setSearchTypeSelection
action’s payload value.src/store.js
For more details and information on customizing the Redux Middleware see:
getDefaultMiddleware
The error A non-serializable value was detected in an action occurs because Redux requires all actions and state to be serializable. In your implementation, the onRowSelectionChange method from material-react-table is passing non-serializable data (like functions or internal properties) into the setSelectedState function, which Redux then attempts to store.
Problem
The onRowSelectionChange function provided by material-react-table contains non-serializable values in its payload, and when you directly dispatch it to Redux, it causes the error.
Solution
You need to ensure that only serializable data (such as row IDs or a simplified version of the selection state) is dispatched to Redux.
Updated Code
Here’s how you can fix this issue:
1. Extract Only Serializable Data:
2. Update Redux Slice:
1. Updated MaterialTable Component
2. Redux Slice Example
Here’s how the Redux slice should handle the serialized data:
Explanation of Changes
Extracting Serializable Data:
Syncing Redux State with MaterialReactTable:
Redux State Structure: