You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在material-react-table v3中用Redux实现rowSelection状态管理?

问题:Material-React-Table v3结合Redux管理行选择状态时出现序列化错误

背景

我正在使用material-react-table v3,组件实现代码如下:

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} />;
    };

当使用useState传递行选择状态和变更回调时完全正常:

const [materialState, setMaterialState] = useState({});

<MaterialTable
  selectedState={materialState}
  setSelectedState={setMaterialState}
/>

但改用Redux管理状态时,尝试了以下代码:

const filters = useSelector((state) => state.filters);
const dispatch = useDispatch();

<MaterialTable
  selectedState={filters.searchTypeSelection}
  setSelectedState={(value: any) =>
      dispatch(setSearchTypeSelection(value))
  }
/>

此时出现错误:

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: ƒ}

我想知道:

  1. 这个错误的原因是什么?
  2. 如何正确用Redux实现material-react-table的状态管理?

解答

错误原因

material-react-table的onRowSelectionChange回调可能接收两种类型的参数:

  • 直接的行选择状态对象(格式如{rowId: true/false})
  • 函数式更新函数(类似React setState的用法,比如(prevState) => newState)

当你把setSelectedState设为(value) => dispatch(setSearchTypeSelection(value))时,如果表格传入的是函数式更新参数,就会把这个函数作为payload传给Redux action。而Redux(尤其是Redux Toolkit默认配置)要求action的payload必须是可序列化的值(不能是函数),因此触发了序列化错误。

解决方法

需要在setSelectedState回调中先处理函数式更新的情况,将其转换为最终的状态值后,再dispatch给Redux:

步骤1:修改父组件的状态变更处理逻辑

在使用MaterialTable的父组件中,新增一个处理函数,统一解析行选择状态的更新值:

const filters = useSelector((state) => state.filters);
const dispatch = useDispatch();

const handleRowSelectionChange = (updater) => {
  // 区分直接值和函数式更新,解析出最终状态
  const newSelection = typeof updater === 'function' 
    ? updater(filters.searchTypeSelection) 
    : updater;
  dispatch(setSearchTypeSelection(newSelection));
};

<MaterialTable
  selectedState={filters.searchTypeSelection}
  setSelectedState={handleRowSelectionChange}
/>

步骤2:确保Redux切片状态可序列化

filters切片中的searchTypeSelection必须是普通可序列化对象(比如{row1: true, row2: false}),不能包含函数或其他非序列化值。示例切片代码如下:

import { createSlice } from '@reduxjs/toolkit';

const initialState = {
  searchTypeSelection: {},
};

const filtersSlice = createSlice({
  name: 'filters',
  initialState,
  reducers: {
    setSearchTypeSelection: (state, action) => {
      state.searchTypeSelection = action.payload;
    },
  },
});

export const { setSearchTypeSelection } = filtersSlice.actions;
export default filtersSlice.reducer;

验证逻辑

修改后,无论表格传入的是直接状态对象还是函数式更新,都会先转换为最终的状态值,再传递给Redux action,避免了将函数作为payload的问题,也就不会触发序列化错误了。


内容的提问来源于stack exchange,提问作者Ravishankar Chatterjee

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 22:34:51