如何在 React 中使用 useState Hook change/add 数组的某一行的值

How to change/add value of a certain row of an array using useState Hook in React

我有以下数组,

const bio = [
  {id: 1, name: "Talha", age: 26}, 
  {id: 2, name: "Ayub", age: 22}
]

这是我的完整代码,

import './App.css';
import React, {useState} from 'react';

const bio = [
  {id: 1, name: "Talha", age: 26}, 
  {id: 2, name: "Ayub", age: 22}
]

const App = () => {

  const [bioData, setbioData] = useState(bio); 
  const clear_function = () => setbioData([])
  return (
    <div className="App">
      {
      bioData.map((arr) =>
      <>
       <h3 key={arr.id}>Name: {arr.name}, Age: {arr.age}</h3>
      <button onClick={() => clear_function()}>Click me</button>
      </>
      )}
    </div>
  );
}

export default App;

现在,这段代码将整个数组挂接到 useState。每当我单击“单击我”按钮时,它会将状态设置为空数组,结果 returns 空数组。

但是如果我想删除数组的特定行怎么办?我制作了两个按钮,每个按钮一排。我想要做的是,如果我单击第一个按钮,它也会从数组中删除第一行并保留第二个数组。

同样,如果我想更改特定行的特定属性值,如何使用 useState 挂钩来实现?例如,我想更改 第二行 name 属性。如何使用 useState 做到这一点?

加法也一样。如果我制作一个表格并尝试在我的生物阵列中添加一个新行,我该怎么做? 我在 Google 上搜索了一下,也找到了类似的 post 但是里面给出的答案并不令人满意并且没有用,这就是我再次问这个问题的原因.

我不确定我是否完全理解你的问题,但是当你想改变功能组件中的状态时,你不能直接改变状态对象,而是需要创建一个新的所需状态对象,然后将状态设置为该对象。 例如,如果您想向数组中添加一个新行,您将执行以下操作:

setbioData((currBioData) => [...oldBioData, {id: 3, name: "Bla", age: 23}]);

当您想根据当前状态更改状态时,可以选择向 setState 函数发送一个接受当前状态的回调函数,然后使用扩展运算符添加一个新行到阵列。 我不打算深入探讨为什么最好通过 setState 函数来修改当前状态,但您可以在 React official docs

中阅读相关内容

如果我对问题的理解正确,我认为您可以将更新后的对象传递给设置状态,仅此而已。

要更改数组中的特定对象,请执行以下操作:

// Update bio data with id = 2
setbioData(prevValue => 
    [...prevValue].map(el => 
        el.id === 2 ? ({...el, name:'new name'}) : el)
    )

还有,你把key设置错了地方

完整的重构代码:

const bio = [
  {id: 1, name: "Talha", age: 26}, 
  {id: 2, name: "Ayub", age: 22}
]
const App = () => {

  const [bioData, setbioData] = useState(bio); 
  const clear_function = (id) => {
    
    setbioData(prevValue => 
      [...prevValue].map(el => 
          el.id === id ? ({...el, name:'new name'}) : el)
      )
  }
  return (
    <div className="App">
      {
      bioData.map((arr) =>
      <div key={arr.id}>
       <h3>Name: {arr.name}, Age: {arr.age}</h3>
      <button onClick={() => clear_function(arr.id)}>Click me</button>
      </div>
      )}
    </div>
  );
}

这里似乎有 3 个问题。我会尽力提供帮助。

  1. "如果我想删除数组的特定行怎么办?" 一种方法是过滤当前数组并使用新数组更新状态。 在您的示例中:onClick={()=>setbioData(arr.filter(row=>row.id !== arr.id))}

  2. “如果我想更改特定行的特定属性值,我该如何使用 useState 挂钩来实现?” 您将需要使用正确的信息创建一个新数组并将该数组保存到状态。 在您的示例中:[... bioData, {id:/row_id/,name:/new name/,age:/new age/}]

  3. “如果我制作一个表格并尝试在我的生物数组中添加一个新行,我该怎么做” 在这种情况下,您会将一个新对象推入您的数组。在你的例子中:

setbioData(previousData=>previousData.push({id:previousData.length+1,name:/new name/,age:/new age/})

希望对你有所帮助,祝你好运

import './App.css';
import React, {useState} from 'react';

const bio = [
  {id: 1, name: "Talha", age: 26}, 
  {id: 2, name: "Ayub", age: 22}
]

const App = () => {

  const [bioData, setbioData] = useState(bio); 
  const clear_function = (i) => {
    let temp = bioData.slice()
    temp = temp.splice(i, 1)
    setbioData(temp)
  }
  return (
    <div className="App">
      {
      bioData.map((arr, i) =>
      <>
       <h3 key={arr.id}>Name: {arr.name}, Age: {arr.age}</h3>
      <button onClick={() => clear_function(i)}>remove row</button>
      </>
      )}
    </div>
  );
}

export default App;

同样的方法,你只需要更新一个特定的属性,只需更新临时数组中的那个元素并执行 setBioData(temp)

同样,如果您想添加另一行,请执行 temp.push({id: 1, name: "Talha", age: 26}) 并执行 setBioData(temp)

使用 react useState 向数组添加一行就像下面这样简单:

function addRow(objToAdd){
 //get old data and add new row
 let newBioData = bioData.push(objToAdd)
 setBioData(newBioData)
}

要删除特定行,您需要在 bioData 数组中找到对象,将其删除并设置新的 bioData,如下所示:

function removeRow(rowId){
 //Filter the array by returning every object with a different Id than the one you want to remove
 let newBioData = bioData.filter(function (value, index, arr){ return value.id != rowId })
 setBioData(newBioData)
    }

要更新状态,您可以像这样使用传播运算符:

        function updateRow(rowId, data){
         //Iterate list and update certain row
         bioData.filter(function (value, index, arr){
          //Row to update
          if(value.id == rowId){
           return {name: data.name, age: data.age}
          }else{
           //Nothing to update, return current item (spread all values)
           return {...value}
          }
         })
         setBioData ([])
        }