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

react-table子组件向父组件传选中行数据时触发更新深度超限错误

解决react-table子组件传递选中行到父组件的无限循环问题

问题根源

你遇到的「Maximum update depth exceeded」错误,本质是状态更新触发组件重新渲染,而重新渲染又再次触发状态更新,形成无限循环。常见触发原因有两个:

  1. 子组件内用useState冗余存储选中状态,且useEffect依赖项设置不当,导致selectedFlatRows变化→调用setSelectedRows→组件重渲染→selectedFlatRows再次变化→重复触发useEffect。
  2. 父组件传递的回调函数未用useCallback包裹,每次父组件渲染都会生成新的函数引用,导致子组件useEffect依赖项变化,触发不必要的更新,进而引发循环。

解决方案

核心思路是去掉子组件内冗余的状态存储,直接将react-table原生的selectedFlatRows通过父组件回调传递,同时确保父组件的回调引用稳定。

步骤1:父组件优化

用useCallback包裹传递给子组件的回调函数,保证其引用不会随父组件渲染频繁变化:

import { useState, useCallback } from 'react';
import ChildTable from './ChildTable';

function Parent() {
  const [selectedRows, setSelectedRows] = useState([]);

  // 用useCallback包裹,依赖项为空数组,确保引用稳定
  const handleRowSelect = useCallback((selectedData) => {
    setSelectedRows(selectedData);
  }, []);

  return (
    <div>
      <ChildTable onRowSelect={handleRowSelect} />
      <div>已选中行:{JSON.stringify(selectedRows)}</div>
    </div>
  );
}

步骤2:子组件优化

直接监听react-table的selectedFlatRows变化,调用父组件的回调,无需额外用useState存储:

import { useTable, useRowSelect } from 'react-table';
import { useEffect } from 'react';

function ChildTable({ columns, data, onRowSelect }) {
  const {
    getTableProps,
    getTableBodyProps,
    headerGroups,
    rows,
    prepareRow,
    selectedFlatRows,
  } = useTable(
    { columns, data },
    useRowSelect,
    (hooks) => {
      // 添加入选列
      hooks.visibleColumns.push((cols) => [
        {
          id: 'selection',
          Header: ({ getToggleAllRowsSelectedProps }) => (
            <input type="checkbox" {...getToggleAllRowsSelectedProps()} />
          ),
          Cell: ({ row }) => (
            <input type="checkbox" {...row.getToggleRowSelectedProps()} />
          ),
        },
        ...cols,
      ]);
    }
  );

  // 监听选中行变化,传递给父组件
  useEffect(() => {
    // 提取选中行的原始数据(可根据需求调整)
    const selectedData = selectedFlatRows.map(row => row.original);
    onRowSelect(selectedData);
  }, [selectedFlatRows, onRowSelect]); // 依赖项包含稳定的回调函数

  // 渲染表格
  return (
    <table {...getTableProps()}>
      <thead>
        {headerGroups.map(headerGroup => (
          <tr {...headerGroup.getHeaderGroupProps()}>
            {headerGroup.headers.map(col => (
              <th {...col.getHeaderProps()}>{col.render('Header')}</th>
            ))}
          </tr>
        ))}
      </thead>
      <tbody {...getTableBodyProps()}>
        {rows.map(row => {
          prepareRow(row);
          return (
            <tr {...row.getRowProps()}>
              {row.cells.map(cell => (
                <td {...cell.getCellProps()}>{cell.render('Cell')}</td>
              ))}
            </tr>
          );
        })}
      </tbody>
    </table>
  );
}

额外注意事项

  • 如果必须在子组件内存储选中状态,一定要确保useEffect的依赖项不会触发循环:比如不要将子组件的selectedRows作为useEffect的依赖,同时避免父组件将selectedRows回传给子组件引发二次更新。
  • 若仍出现循环,可检查selectedFlatRows是否在每次渲染时都生成新的引用(react-table的selectedFlatRows是稳定的,除非数据或选中状态真的变化),必要时可通过useMemo对选中数据做浅比较优化。

内容的提问来源于stack exchange,提问作者Nitin T

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 02:20:33