[英]How to push a new element to nested array react hooks
我正在嘗試將一個新元素推送到我的嵌套數組,但我面臨的問題是它每次都在創建新數組,我知道這很愚蠢,但我嘗試谷歌但沒有得到答案。
我在做什么
下面是我的 state
const [state, setState] = useState([ { name: "test", lname: "lname", ages: [ { age: 30 } ] } ]);
我在點擊時想要做的是
const randomAge = () => { let rg = ((Math.random() * 1000) / 10).toFixed(); setState({...state, ages: {...state.ages, age: rg } }); };
但是它返回非常錯誤的output,如下圖所示
{
"0": {
"name": "test",
"lname": "lname",
"ages": [
{
"age": 30
}
]
},
"ages": {
"rg": "34"
}
}
我想要的 Output 如下所示
[
{
"name": "test",
"lname": "lname",
"ages": [
{
"age": 30
},
{
"age": 50
},
{
"age": 60
}
]
}
]
我知道我在某處犯了一個非常愚蠢的錯誤,但現在我找不到
我只是想通過單擊按鈕將新的隨機年齡推送到我的年齡數組
您的示例並不完全清楚,但您需要 [] 將年齡定義為元素數組。 喜歡:
使用 prev "prevState" 參數。 不是參考 state。 state 不保證是最新的。
希望這可以幫助:
setState((prev) => ([...prev.filter((a,i) => i !== 0), {...prev[0], ages: [...prev[0].ages, {age:12}]} ]))
或根據元素使用選擇器過濾要編輯的元素:
setState((prev) => ([...prev.filter((a) => a.name !== "test"), {...prev.find(a=> a.name === "test"), ages: [...prev.find(a=> a.name === "test").ages, {age:12}]} ]))
做同樣的事情。 這種復雜性的一部分歸因於這樣一個事實,即您的基本元素是一個數組。
您當然可以構建子功能以增加可讀性。 但基礎不會改變。
我不確定,但是,您在開始 state ages: [ {age: 30} ]
但在 setState setState({...state, ages: {...state.ages, age: rg } });
中使用數組您使用 object 而不是 Array
幾點注意事項:
.ToFixed()
返回一個字符串而不是數字類型{...state, ages: [...state.ages, {age: rg} ] }
這是因為ages 是一個數組,因此您需要對數組使用展開運算符句法編輯:
https://stackblitz.com/edit/react-jkgjf4?file=src/App.js
工作 stackblitz,簡而言之,你的 object 是一個數組,所以我們需要像這樣對待它並循環它,因為我們正在創建一個新的 object。 這樣更新它比嘗試使用擴展運算符更容易,因為它很快就會變得非常難看。
const [state, updateState] = useState([
{
name: 'test',
lname: 'lname',
ages: [
{
age: 30,
},
],
},
]);
function update() {
//turning it into an int
let rg = Number.parseInt(((Math.random() * 1000) / 10).toFixed());
let newState = [...state];
newState.forEach((x) => x.ages.push({ age: rg }));
console.log('new State: ', newState);
updateState(newState);
}
您的初始 setState() 應該是 object 而不是數組。
const [state, setState] = useState(
{
name: "test",
lname: "lname",
ages: [
{
age: 30
}
]
}
);
根據 function randomAge嘗試以下
const randomAge = () => {
let rg = ((Math.random() * 1000) / 10).toFixed();
setState({
...state,
ages: [
...state.ages,
{
age : rg
}
]
});
};
您會看到 state object 中的年齡已更改為數組。 使用擴展運算符,您可以將之前的 state 年齡數組復制到其中。 這應該是您的代碼中較小的對象,最后您正在創建另一個 object,其中age: rg作為唯一的對值。
將年齡保留為數組並簡單地將rg值推入其中而不是創建對象可能會更好。 除非您要添加多個 KEY:VALUE 對。
只需像這樣更改您的 randomAge function 即可。
const randomAge = () => {
const rg = ((Math.random() * 1000) / 10).toFixed();
const newAgesArray = state[0].ages;
newAgesArray.push({ age: rg });
setState([...state, { ages: newAgesArray }]);
};
考慮到整個數組中只有一項,我使用了索引0 。
此外const newAgesArray = state[0].ages
不會創建數組的全新副本,它只是創建一個引用。 它可以工作,但在使用 state 時並不理想。 我建議您改為做一些淺拷貝或深拷貝 - DYOR 。
當前代碼正在將 state 不變量從 arrays 變異為對象。
const randomAge = () => { let rg = ((Math.random() * 1000) / 10).toFixed(); setState({...state, ages: {...state.ages, age: rg } }); };
如果state
數組中只有一個元素,則使用功能性 state 更新並創建一個新數組引用,其中僅包含單個 object 元素。 淺拷貝前一個狀態的state[0]
元素並通過淺拷貝數組和附加新的 object 和age
屬性來更新ages
屬性。
例子:
const randomAge = () => {
const age = (Math.random() * 100).toFixed();
setState((prev) => [
{
...prev[0],
ages: [...prev[0].ages, { age }]
}
]);
};
If you are eventually wanting to handle multiple object elements in the state
array then I suggest adding a GUID to each object and pass this to the randomAge
callback so it can correctly update the correct state.
例子:
import React, { useState } from "react";
import { nanoid } from "nanoid";
export default function App() {
const [state, setState] = useState([
{
id: nanoid(),
name: "test1",
lname: "lname1",
ages: []
},
{
id: nanoid(),
name: "test2",
lname: "lname2",
ages: []
}
]);
const randomAge = (id) => () => {
const age = (Math.random() * 100).toFixed();
setState((prev) =>
prev.map((el) =>
el.id === id
? {
...el,
ages: el.ages.concat({ age })
}
: el
)
);
};
return (
<div className="App">
{state.map((li, ind) => {
return (
<React.Fragment key={li.id}>
<div>{li.name}</div>
<div>{li.lname}</div>
<br />
{li.ages.map((d) => <div>{d.age}</div>)}
<button onClick={randomAge(li.id)}>Add random age</button>
</React.Fragment>
);
})}
</div>
);
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.