簡體   English   中英

如何使用 useState 掛鈎按索引更新數組?

[英]How to update an array by index using the useState hook?

我有一個 select 組件,我想用它來根據索引更新對象數組的值。

我使用這樣的鈎子:

const [areas, setAreas] = useState(product.areas);

這將為“區域”返回以下內容:

[
  0: {de: "Getraenke", en: "Drinks"},
  1: {de: "Snacks", en: "Snacks"}
]

我的 select 組件如下所示:

{areas?.map((area: {de: string, en: string}, index: number) => (
  <Wrapper key={index}>
    <Select
      label="Area"
      name="product-area"
      value={area[lang] || ''}
      onChange={e => setArea([...area, { [lang]: e.target.value }])}
    >
      {areaOptions.map(option => (
        <option value={option} key={option}>
          {option}
        </option>
      ))}
    </Select>
  </InputWrapper>
))}

通過這種方式,在選擇一個選項(此處為“Sweets”)后,我不幸地得到以下“區域”:

[
  0: {de: "Getraenke", en: "Drinks"},
  1: {de: "Snacks", en: "Snacks"}
  2: {en: "Sweets" }
]

所以數組的第一個 object 沒有按預期更新,而是附加了另一個 object,不幸的是它也缺少“de”語言。

我的目標是更新數組的第一個 object(或基於 select 組件索引的 object 組件),而不是:

  0: {de: "Getraenke", en: "Drinks"}

..更新后的 object 如下所示:

  0: {de: "Suessigkeiten", en: "Sweets"}

因此,應根據當前 select 組件的索引更新數組中的對象,並考慮所選語言(默認為“en”)。

讓我們一步一步解決這個問題

1. 附加了另一個 object

那是因為你告訴它這樣做:)

onChange={e => setArea([...area, { [lang]: e.target.value }])}

這意味着,復制整個數組...area並在末尾添加一個新的 object { [lang]: e.target.value }

您犯的另一個錯誤是沒有使用回調 function,訪問當前...area的正確方法應該是:

onChange={e => setArea((currentArea) => [...currentArea, { [lang]: e.target.value }]}

這樣,您始終擁有最新版本的area

現在,要通過索引更新特定的 object,您可以執行以下操作:

onChange={e => setArea((currentArea) => {
  const { value } = e.target;
  
  const newArea = currentArea.map((singleArea, areaIndex) => {
    if (areaIndex === index) {
      return { [lang]: value }
    }
 
    return singleArea;
  });

  return newArea;
}}

2. 缺乏“de”語言

同樣,您明確地只添加了一種語言:)

{ [lang]: value } // { en: 'something' }

不知道如何為你解決這個問題,但至少你可以理解它為什么錯了,它應該是這樣的(只是一個概念,這不起作用):

{ [langDe]: value, [langEn]: value } // { de: 'Guten Tag', en: 'something' }

最簡單的方法是克隆數組,按索引更新特定數組項,然后使用 useState 將舊數組替換為舊數組,如下所示。

const updateArea = (e, lang, index) => {
  const updatedAreas = [...areas];
  updatedArea[index][lang] = e.target.value;
  setAreas(updatedAreas);
}

...

{areas?.map((area: {de: string, en: string}, index: number) => (
  <Wrapper key={index}>
    <Select
      label="Area"
      name="product-area"
      value={area[lang] || ''}
      onChange={e => updateArea(e, lang, index)}
    >
      {areaOptions.map(option => (
        <option value={option} key={option}>
          {option}
        </option>
      ))}
    </Select>
  </InputWrapper>
))}

暫無
暫無

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

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