如何在 React 中使用 useState Hook 更改/添加数组的某一行的值

Posted

技术标签:

【中文标题】如何在 React 中使用 useState Hook 更改/添加数组的某一行的值【英文标题】:How to change/add value of a certain row of an array using useState Hook in React 【发布时间】:2021-10-21 19:51:14 【问题描述】:

我有一个如下数组,

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 挂钩。每当我单击“单击我”按钮时,它会将状态设置为空数组并返回空数组。

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

同样,如果我想更改特定行的特定属性值,我该如何使用 useState 挂钩呢?例如,我想更改第二行name属性。 useState 怎么可能做到这一点?

加法也是一样的。如果我制作一个表格并尝试在我的生物数组中添加一个新行,我该怎么做? 我在谷歌上搜索了它,也找到了一个类似的帖子,但其中给出的答案并不令人满意,也没有奏效,这就是我再次问这个问题的原因。

【问题讨论】:

【参考方案1】:

使用 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 ([])
        

【讨论】:

感谢您的回复。我理解这些并且也已经实施了它们,它们就像你说的那样工作。但我的问题是如何更新特定的行值?例如,我想将 bioData[1].name 的值更新为不同的值。如何使用 useState 钩子和 Button 的 onClick 来做到这一点。 我已经更新了我的帖子,希望对你有帮助! :)【参考方案2】:

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

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

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

【讨论】:

这行得通,谢谢。但我的主要问题是,如何更新特定的行值?例如,我想将 bioData[1].name 的值更新为不同的值。如何使用 useState 钩子和 Button 的 onClick 来做到这一点。【参考方案3】:

这里似乎有 3 个问题。我会尽力帮忙的。

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

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

    “如果我创建一个表单并尝试在我的 bio 数组中添加一个新行,我将如何做” 在这种情况下,您会将一个新对象推送到您的数组中。在您的示例中:

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

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

【讨论】:

感谢您的回复。我完全理解移除和插入部分,它们也为我工作。我唯一的问题是,如何在更新行的情况下进行检查?确保仅更新特定行(单击哪个按钮)的检查?例如,如果按钮的 id = 2,则更新我的数组的第二行,而不是任何其他 这是一个非常相似的问题,答案比我能给出的要好。我希望它有帮助! ***.com/questions/28121272/…【参考方案4】:
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;

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

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

【讨论】:

我试过这个实现。它适用于删除一行,谢谢。但不幸的是,当我尝试更新特定行的值时它不起作用。例如,我在clear_function 函数中做了这个:let temp = bioData.slice()temp[1].name = "Hello World";setbioData(temp)。但它没有更新第二行的名称。【参考方案5】:

如果我理解正确的问题,我认为您可以将更新的对象传递给设置状态,就是这样。

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

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

【讨论】:

这对我不起作用:/我试图这样做...&lt;button onClick=() =&gt; setbioData(bioData=&gt; [...bioData].map(e1 =&gt; e1.id === 2 &amp;&amp; e1.name='new name')) type="button"&gt;Click me&lt;/button&gt;...它在 e1 上出现错误,即Parsing error: Invalid left-hand side in assignment expression。并在 e1.name 和 &lt;/button&gt; 上给出错误。我似乎无法理解问题 @TalhaAyub 我已经更新了代码,看看。

以上是关于如何在 React 中使用 useState Hook 更改/添加数组的某一行的值的主要内容,如果未能解决你的问题,请参考以下文章

如何使用映射 React 从 useState 添加 2 个键?

如何在 react native 中使用选择器从 redux 状态设置 usestate 的初始值?

useState hook如何知道react中的调用上下文

如何在 React 中使用 useState Hook 更改/添加数组的某一行的值

如何在 React 函数组件(useState 挂钩)中访问 ag-Grid API?

如何使用 useState 在点击时显示/隐藏移动导航栏? React + TypeScript + Tailwind 项目