3

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.

Awais Shahid
  • 117
  • 4
  • 15

5 Answers5

3

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>
  );
}
spark
  • 1,271
  • 1
  • 12
  • 18
  • This is not working for me :/ I tried to do this... ``... It gives an error on e1, that is `Parsing error: Invalid left-hand side in assignment expression`. And also give errors on e1.name as well as on ``. I can't seem to understand the problem – Awais Shahid Aug 20 '21 at 10:06
  • @TalhaAyub I have updated the code, have a look. – spark Aug 20 '21 at 10:26
1

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

amitlisha
  • 140
  • 1
  • 8
  • This works, thank you. But my major question was, how do I update a specific row value? For example, I want to update the value for bioData[1].name to something different. How can I do that using useState hook and the onClick of Button. – Awais Shahid Aug 20 '21 at 10:07
1

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

  • Thanks for the reply. I fully understand the Removing and Insertion part and they are working for me as well. My only question is, how do I place a check in case of Updating a row? A check which ensures that only the specific row (for which button is clicked) is being updated? Like for example, if the button has id = 2, then update the second row of my array and not any other – Awais Shahid Aug 20 '21 at 10:00
  • Here's a very similar problem with a better answer than I could give. I hope it helps! https://stackoverflow.com/questions/28121272/whats-the-best-way-to-update-an-object-in-an-array-in-reactjs – ultideveloper Aug 20 '21 at 12:50
1
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)

dj21496
  • 96
  • 7
  • I tried this implementation. It works well for the deletion of an row, thank you. But it is unfortunately not working when I try to update a specific row's value. For example, I did this in the `clear_function` function: `let temp = bioData.slice()` `temp[1].name = "Hello World";` `setbioData(temp)`. But it did not update the name for the 2nd row. – Awais Shahid Aug 20 '21 at 10:10
1

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 ([])
        }
Julianvv
  • 100
  • 10
  • Thanks for the reply. I understand these and have implemented them as well, they work as you said. But my question was how do I update a specific row value? For example, I want to update the value for bioData[1].name to something different. How can I do that using useState hook and the onClick of Button. – Awais Shahid Aug 20 '21 at 10:08
  • I've updated my post, hope this helps you! :) – Julianvv Aug 20 '21 at 10:51