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

React如何创建独立备份状态,实现可编辑表格修改后可重置回初始数据

问题根源

你遇到的变量同步修改问题是浅拷贝导致的对象引用共享:

  • 扩展运算符[...数组]仅能复制数组本身的结构,数组内部存储的所有对象依然指向原始budgetData中的对象内存地址
  • 你修改selectedData[row][name]时,本质是修改了所有变量共享的同一个对象,因此dataBackup、原始budgetData都会同步变化
  • 额外的问题:dataBackup定义在组件函数体内,每次组件重渲染都会重新生成,且你直接将budgetData传给useState作为初始值,也会导致原始静态数据被意外修改

修复方案

我们不需要额外维护dataBackup变量,直接基于原始静态数据做深拷贝即可,修改两处核心逻辑:

  1. 初始化state和重置时,都对原始数据做全量拷贝,每个行对象单独复制
  2. 处理输入变更时,先复制要修改的行对象再更新属性,避免修改原引用

修正后完整代码

import {useState} from 'react';
  
const budgetData = 
      [ 
        {   index: 0, category: 'Housing',   item: 'Mortgage',  amount: 650.99 },
        {   index: 1, category: 'Housing',   item: 'Insurance', amount: 275.50 }, 
        {   index: 2, category: 'Utilities', item: 'Hydro',     amount:  70.00 }      
      ];

// 工具函数:拷贝预算数据,避免引用共享
const copyBudgetData = () => budgetData.map(item => ({...item}));

function UpdateBudget()  {
    const [dataWorking, setDataWorking ] = useState(copyBudgetData()); 

    const handleChange = (e, row) => {
      // 先拷贝整个数组
      let selectedData = [...dataWorking];
      const {name, value} = e.target;
      // 再拷贝要修改的行对象,避免修改原引用
      selectedData[row] = {...selectedData[row], [name]: value};
      setDataWorking(selectedData);
    };

    const handleReset = () => {
      // 重置时重新拷贝原始数据即可
      setDataWorking(copyBudgetData());
    };


    return  (
      <div>
        <table>
          <thead>
            <tr>
              <th>Category</th> <th>Item</th> <th>Amount</th>
            </tr>
          </thead>

          <tbody>
              { dataWorking.map( (row) =>  (
                  <tr key={row.index}>
                    <td> <input value={row.category} name="category" onChange={(e) => handleChange(e, row.index)}/> </td>
                    <td> <input value={row.item    } name="item"     onChange={(e) => handleChange(e, row.index)}/> </td>
                    <td> <input value={row.amount  } name="amount"   onChange={(e) => handleChange(e, row.index)}/> </td>
                  </tr>
                ))
              }
          </tbody>
        </table>
        <div> 
            <button onClick={handleReset}> Discard Changes </button>
        </div>
        <div style={{ marginTop: 20, fontSize: 10 }}> * budgetData  {budgetData.length}  * {JSON.stringify(budgetData)}  </div> 
        <div style={{ marginTop: 20, fontSize: 10 }}> * dataWorking {dataWorking.length} * {JSON.stringify(dataWorking)} </div> 
      </div>
    );
}
   
export default UpdateBudget;

优化说明

如果你的初始数据是从接口动态获取的而非静态常量,可以用useRef存储备份数据:

// 初始数据加载完成后存储备份
const dataBackup = useRef(copyBudgetData(originData));
// 重置时使用
setDataWorking(copyBudgetData(dataBackup.current));

内容的提问来源于stack exchange,提问作者Keith Arnold

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 16:15:03