簡體   English   中英

如何將新元素推送到嵌套數組反應掛鈎

[英]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 不保證是最新的。

  • 考慮 12 你的隨機數:
  • 我們更新您的人員數組中的第一個元素(索引 0)

希望這可以幫助:

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()返回一個字符串而不是數字類型
  • 您希望您的 setState 看起來像{...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 }]
    }
  ]);
};

編輯 how-to-push-a-new-element-to-nested-array-react-hooks

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>
  );
}

編輯 how-to-push-a-new-element-to-nested-array-react-hooks (forked)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM