Awais Shahid
Awais Shahid

Reputation: 137

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

I have a following array,

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

Here is a complete code of mine,

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;

Now, this code hooks the whole array to useState. Whenever I click the button "Click me", it sets the state to empty array and returns empty array as a result.

But what if I want to remove a specific row of the array? I have made two buttons, each for one row. What I want to do is if I click the first button, it removes the first row from the array as well and keeps the 2nd array.

Similarly, if I want to change a specific attribute value of a specific row, how can I do that using useState hook? For example, I want to change the name attribute of the 2nd row. How is it possible to do this with useState?

And same case for addition. IF I make a form and try to add a new row into my bio array, how would I do that? I searched it up on Google, found a similar post as well but the answer given in it wasn't satisfactory and did not work, which is why I am asking this question again.

Upvotes: 3

Views: 3656

Answers (5)

Julianvv
Julianvv

Reputation: 108

Adding a row to the array with react useState would be as simple as the following:

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

To remove a specific row you would need to find the object within the bioData array, remove it and set the new bioData like so:

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

To update the state you could use the spread operator like so:

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

Upvotes: 1

spark
spark

Reputation: 1381

If I understood the question right, I think you can pass the updated object to set state and that'll be it.

To change a particular object in array, do something lie this:

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

Also, you have set key at the wrong place

Full refactored code:

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

Upvotes: 3

dj21496
dj21496

Reputation: 96

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;

Same way you need to just to update a specific attribute just update that element in the temp array and do setBioData(temp)

Similarly, If you want to add another row do temp.push({id: 1, name: "Talha", age: 26}) and do setBioData(temp)

Upvotes: 1

ultideveloper
ultideveloper

Reputation: 11

Looks like there are 3 questions here. I'll do my best to help.

  1. "what if I want to remove a specific row of the array?" One way is to filter your current array and update the state with the new array. In your example: onClick={()=>setbioData(arr.filter(row=>row.id !== arr.id))}

  2. "if I want to change a specific attribute value of a specific row, how can I do that using useState hook?" You will need to create a new array with the correct information and save that array to state. In your example: [... bioData, {id:/row_id/,name:/new name/,age:/new age/}]

  3. "IF I make a form and try to add a new row into my bio array, how would I do that" In this case, you would push a new object into your array. In your example:

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

I hope this helps you, best of luck

Upvotes: 1

amitlisha
amitlisha

Reputation: 140

I'm not sure if I fully understand your question, but when you want to change the state in a functional component, you can't directly change the state object, instead you need to create a new desired state object, and then set the state to that object. for example, if you want to add a new row to your array, you'll do the following:

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

When you want to change the state based on the current state, there's an option to send the setState function a callback function which accepts the current state, and then using the spread operator we add a new row to the array. I'm not going to get into why it is better to pass setState a function to modify current state but you can read about it in React official docs

Upvotes: 1

Related Questions