我如何在React中创建一个单独的备份状态,以便我可以编辑一组数据,但在需要时重置为备份?



我向用户展示了一个预先填充了数据的可编辑表,并希望包含一个'丢弃更改'按钮,该按钮将调用handleReset()函数来恢复'活动'数据集(一个对象数组)到它的原始状态。

我所采取的方法是将数据读取到一个名为'dataBackup'的变量中,也读取到一个名为'dataWorking'的状态变量中。其想法是,用户编辑将应用于dataWorking,而dataBackup将保持不变,并可用于在需要时重置dataWorking。但是,当编辑表时,修改同时应用于。变量!

我是React的新手,我不理解这种行为。我也不确定我选择的方法是否是处理此功能的最佳方法,因为我还没有找到任何类似的示例。感谢一些指点,并添加了我的样例代码属于演示发生了什么。

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 }      
];
function UpdateBudget()  {
const  dataBackup = [...budgetData];
const [dataWorking, setDataWorking ] = useState(budgetData); 
const handleChange = ( (e, row) => {
let selectedData = [...dataWorking];
const {name, value} = e.target;
selectedData[row][name] = value;
setDataWorking(selectedData);
});
const handleReset = ( (e) => {
setDataWorking(dataBackup);
});

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={ (e) => handleReset (e)}> 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 style={{ marginTop: 20, fontSize: 10 }}> * dataBackup  {dataBackup.length}  * {JSON.stringify(dataBackup)}  </div>
</div>
);
}

export default UpdateBudget;

你看到dataBackup更新后,你的状态改变是因为你复制数组内的对象引用。如果您想拥有一个完全未引用的budgetData副本,最简单的解决方案是

将使用JSON方法(但我建议研究一下对象的深度复制是什么):

const  dataBackup = JSON.parse(JSON.stringify(budgetData))

一般来说,存储不会导致UI呈现的值的最佳实践是使用useRef:

const  dataBackup = React.useRef(JSON.parse(JSON.stringify(budgetData)))
// then access it like that
dataBackup.current

另一件事,在你的handleChange中,你实际上是在改变状态,这应该避免:

selectedData[row][name] = value;

理想情况下,你应该拼接和扩展这些对象,这样你就不会直接修改状态,或者使用一些深度复制方法。