英文:
Complex setState in React
问题
以下是您要翻译的部分:
我有一个包含订单列表的页面,每个订单都有唯一的orderId。页面上的每个订单部分都有两个文本框,一个用于trackingID,另一个用于carrierName。我希望我的输入对象 - 使用setInput函数更新 - 能够“记住”所有已更新的订单。
我编写了以下代码,但如果我编辑属于不同orderId的文本框,它会覆盖输入变量。
const updateStatus = (e) => {
const { id, value, name } = e.target;
if (name === "trackingId") {
setInput((prevState) => ({
...prevState,
orderId: prevState.orderId || id,
shipData: [{ ...prevState.shipData[0], trackingId: value }],
}));
} else if (name === "carrierName") {
setInput((prevState) => ({
...prevState,
orderId: prevState.orderId || id,
shipData: [{ ...prevState.shipData[0], carrierName: value }],
}));
}
console.log(`inputs are: ${JSON.stringify(input)}`);
};
以上代码在我编辑carrierName和trackingId文本框后生成以下对象:
{"orderId":"1","shipData":[{"carrierName":"carrierOne","trackingId":"TrackingOne"}]}
相反,如果我编辑第二个orderId的carrierName和trackingId文本框,我希望代码创建以下对象,即我希望状态保留先前的状态:
{"orderId":"1","shipData":[{"carrierName":"carrierOne","trackingId":"TrackingOne"}]},{"orderId":"2","shipData":[{"carrierName":"carrierTwo","trackingId":"TrackingTwo"}]}
出于某种原因,我无法使其正常工作,真的很感激那些比我聪明的人的帮助!
<details>
<summary>英文:</summary>
I have a page that contains a list of orders, each with a unique orderId. Each order section on the page has two text boxes, one for trackingID and one for carrierName. I would like my input object - that is updated using the setInput function - to 'remember' all the orders that have been updated.
I have written the following code, but it overwrites the input variable if I edit a text box belonging to a different orderId.
const updateStatus = (e) => {
const { id, value, name } = e.target;
if (name === "trackingId") {
setInput((prevState) => ({
...prevState,
orderId: prevState.orderId || id,
shipData: [{ ...prevState.shipData[0], trackingId: value }],
}));
} else if (name === "carrierName") {
setInput((prevState) => ({
...prevState,
orderId: prevState.orderId || id,
shipData: [{ ...prevState.shipData[0], carrierName: value }],
}));
}
console.log(`inputs are: ${JSON.stringify(input)}`);
};
The code above produces the following object, after I edit carrierName and trackingId text boxes:
{"orderId":"1","shipData":[{"carrierName":"carrierOne","trackingId":"TrackingOne"}]}
I would like the code to, instead, create this object, if I edit a second orderId's carrierName and trackingId text boxes, i.e., I want the state to keep the previous state:
{"orderId":"1","shipData":[{"carrierName":"carrierOne","trackingId":"TrackingOne"}]},{"orderId":"2","shipData":[{"carrierName":"carrierTwo","trackingId":"TrackingTwo"}]}
For some reason, I just cannot make it work and I would really appreciate the help of someone who is cleverer than I am!
</details>
# 答案1
**得分**: 0
你在这两种情况下都在`setInput`中覆盖了你的输入 - 你要管理的状态只是一个对象,而不是你想要的数组。
那里的状态是:
```javascript
{
orderId: number,
shipData: Array<{ trackingValue: string, carrierName: string }>
}
看起来你想要的输出是拥有一个像这样的状态:
Array<{
orderId: number,
shipData: Array<{ trackingValue: string, carrierName: string }>
}>
让我快速为你准备一个解决方案 - 你可能想要在这里通过订单ID进行索引,而不是将它们存储在一个数组中。
编辑:
const App = () => {
const [input, setInput] = React.useState({});
const updateShipDataForOrder = (orderId, shipData) => {
setInput((prevState) => {
// 创建基于先前数据+新条目的新船数据
const newShipData = {
...prevState[orderId],
...shipData,
};
// 在我们的状态中覆盖该值
const newState = {
...prevState,
[orderId]: newShipData
};
return newState;
})
}
const updateStatus = (e) => {
const { id, value, name } = e.target;
updateShipDataForOrder(id, { [name]: value })
};
// 转换回你想要的数组
const result = Object.entries(input).map(([orderId, shipData]) => {
return {
orderId,
shipData
}
})
return (
<div>
<div>
<h1>Order one</h1>
Tracking ID: <input id="1" name="trackingId" onChange={updateStatus} />
Carrier Name: <input id="1" name="carrierName" onChange={updateStatus} />
</div>
<div>
<h1>Order two</h1>
Status: <input id="2" name="trackingId" onChange={updateStatus} />
Carrier Name: <input id="2" name="carrierName" onChange={updateStatus} />
</div>
<br />
<div>result: {JSON.stringify(result, null, '\t')}</div>
</div>
)
}
const root = document.getElementById('root')
ReactDOM.render(<App />, root)
英文:
You are overwriting your input with setInput
here in both cases - the state you are managing is just an object rather than an array like you want.
The state there is:
{
orderId: number,
shipData: Array<{ trackingValue: string, carrierName: string }>
}
It seems like the output you want is to have a state like
Array<{
orderId: number,
shipData: Array<{ trackingValue: string, carrierName: string }>
}>
Let me whip up a quick solution - you probably want to index here by the orderId rather than storing these in an array.
Edit:
<!-- begin snippet: js hide: false console: true babel: true -->
<!-- language: lang-js -->
const App = () => {
const [input, setInput] = React.useState({});
const updateShipDataForOrder = (orderId, shipData) => {
setInput((prevState) => {
// Create new ship data based on the previous data + new entry
const newShipData = {
...prevState[orderId],
...shipData,
};
// Overwrite that value in our state
const newState = {
...prevState,
[orderId]: newShipData
};
return newState;
})
}
const updateStatus = (e) => {
const { id, value, name } = e.target;
updateShipDataForOrder(id, { [name]: value })
};
// Convert back to the array you wanted
const result = Object.entries(input).map(([orderId, shipData]) => {
return {
orderId,
shipData
}
})
return (
<div>
<div>
<h1>Order one</h1>
Tracking ID: <input id="1" name="trackingId" onChange={updateStatus} />
Carrier Name: <input id="1" name="carrierName" onChange={updateStatus} />
</div>
<div>
<h1>Order two</h1>
Status: <input id="2" name="trackingId" onChange={updateStatus} />
Carrier Name: <input id="2" name="carrierName" onChange={updateStatus} />
</div>
<br />
<div>result: {JSON.stringify(result, null, '\t')}</div>
</div>
)
}
const root = document.getElementById('root')
ReactDOM.render(<App />, root)
<!-- language: lang-html -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.13.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.13.1/umd/react-dom.production.min.js"></script>
<div id="root"></div>
<!-- end snippet -->
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论