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

React中useState在按钮onClick事件中无法更新状态的问题

解决React中editorCellRenderer按钮onClick无法获取最新rowsData的问题

这是典型的闭包陷阱:你的onClick函数是在组件初始渲染时创建的,它捕获了当时的rowsData(空数组)。之后即使通过API更新了rowsData,这个旧函数里的闭包变量不会自动同步最新值,所以你始终拿到空数组。

给你几个可行的解决方案:

方案1:用useRef保存最新状态

通过useRef来存储rowsData的最新引用,这样不管闭包什么时候执行,都能拿到最新的数据:

import { useState, useRef, useEffect } from 'react';

function YourComponent() {
  const [rowsData, setRowsData] = useState([]);
  const rowsDataRef = useRef([]);

  // 同步rowsData到ref
  useEffect(() => {
    rowsDataRef.current = rowsData;
  }, [rowsData]);

  // 定义columns时,onClick里用ref.current
  const columns = [
    // 其他列配置...
    {
      key: 'edit',
      editorCellRenderer: () => (
        <button onClick={() => {
          // 这里就能拿到最新的rowsData了
          console.log(rowsDataRef.current);
          // 执行你的编辑逻辑
        }}>保存</button>
      )
    }
  ];

  // API获取数据的逻辑
  useEffect(() => {
    fetch('/your-api')
      .then(res => res.json())
      .then(data => setRowsData(data));
  }, []);

  return <YourTable columns={columns} data={rowsData} />;
}

方案2:用函数式更新获取最新状态

如果你的需求是更新rowsData,可以直接使用setRowsData的函数式写法,它会自动传入最新的状态值,完全绕开闭包问题:

const handleSaveClick = () => {
  setRowsData(prevRows => {
    // prevRows就是当前最新的rowsData
    const updatedRows = prevRows.map(row => {
      // 根据你的编辑逻辑修改行数据
      if (row.id === currentEditingId) {
        return {...row, editedField: newValue};
      }
      return row;
    });
    return updatedRows;
  });
};

// 在columns里使用这个函数
const columns = [
  {
    key: 'edit',
    editorCellRenderer: () => <button onClick={handleSaveClick}>保存</button>
  }
];

方案3:让columns依赖rowsData重新生成

把columns放在useMemo中,依赖rowsData。这样每次rowsData更新时,都会重新生成columns数组,里面的onClick函数也会捕获最新的rowsData:

import { useState, useMemo } from 'react';

function YourComponent() {
  const [rowsData, setRowsData] = useState([]);

  const columns = useMemo(() => [
    // 其他列配置...
    {
      key: 'edit',
      editorCellRenderer: () => (
        <button onClick={() => {
          console.log(rowsData); // 这里是最新值
        }}>保存</button>
      )
    }
  ], [rowsData]); // 依赖rowsData,更新时重新生成columns

  // API获取数据...

  return <YourTable columns={columns} data={rowsData} />;
}

为什么之前的useEffect没用?

你之前的useEffect可能只是更新了某个变量,但没有触发columns的重新生成——旧的editorCellRenderer和里面的onClick函数依然在被表格组件使用,自然还是拿着旧的闭包值。

内容的提问来源于stack exchange,提问作者Jalak Patoliya

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 19:47:34