7

I am trying to update a single key value pair in an array of objets using React.

Here is the setup

An array of objects

const array = [
  {id:1,name:'Tyler',age:23},
  {id:2,name:'Lauren',age:28},
  {id:3,name:'Nico',age:14},
]

Given an id and age, I want to be able to update the single object that matches the id. For example, given an id of 2 and age of 56, {id:2,name:'Lauren',age:28} should change to {id:2,name:'Lauren',age:56}

My approach

I've set up useState to copy the array of object. However, I am struggling to filter out for the selected id, change the age, and return the updated array.

This is what I currently have:

import { useState } from "react";

const array = [
  { id: 1, name: "Tyler", age: 23 },
  { id: 2, name: "Lauren", age: 28 },
  { id: 3, name: "Nico", age: 14 }
];

export default function App() {
  const [list, setList] = useState(array);

  const updateAge = (id = 2, age = 56) => {
    setList([...list, list.filter((item) => item.id === id)]);
  };

  return (
    <>
      <ul>
        {list.map((item) => {
          return (
            <li>
              {item.name} | {item.age}
            </li>
          );
        })}
      </ul>
      <button onClick={updateAge}>Update age</button>
    </>
  );
}

Here is my codesandbox link

5

3 Answers 3

11

You can use the map function to produce a new array to set the state with.

const updateAge = (id, age) => {
    console.log(id, age);
    setList(
      list.map((item) => {
        if (item.id === id) {
          return { ...item, age };
        } else {
          return item;
        }
      })
    );
  };

If the id matches, it will merge the new age, otherwise it will return the item unchanged.

Note that it will only produce new objects for updated age, the rest will be the same references. That is to say it will be a new array, but most objects (except the changed one) will be the same. If you want new objects you can return { ...item } in the else clause as well.

In this particular case React will only be concerned that you set the state with new array.

Here's the sandbox

Sign up to request clarification or add additional context in comments.

1 Comment

I enjoy the simplicity of this solution. I've changed the if else statement to be a ternary operation for brevity. js setList( list.map((item) => { return item.id === id ? {...item, age} : item }) )
5
import  { useState } from "react";
const array = [
 { id: 1, name: "Tyler", age: 23 },
 { id: 2, name: "Lauren", age: 28 },
 { id: 3, name: "Nico", age: 14 }
];

export default function App() {
  const [list, setList] = useState(array);

  const updateAge = (id, age) => {
    // Find the item to update and store it in new list 
    let el = list.map((item) => {if(item.id === id){item.age=age}return 
     item});
    // Set the previous list to the new list
    setList(el)
    console.log(list)

 };

 return (
   <>
     <ul>
       {list.map((item, index) => {
          return (
           <li key={index}>
             {item.name} | {item.age}
           </li>
         );
        })}
      </ul>
      <button onClick={()=>updateAge(2, 56)}>Update age</button>
    </>
  );
}

Went to your codesandbox link changed it a bit does what you were trying to do now used Map instead of filter hope this helps

Comments

1

You can update you array like this

import { useState } from "react";
const array = [
  { id: 1, name: "Tyler", age: 23 },
  { id: 2, name: "Lauren", age: 28 },
  { id: 3, name: "Nico", age: 14 }
];

export default function App() {
  const [list, setList] = useState(array);

  const updateAge = (id = 2, age = 56) => {
    setList(list.map(l=>l.id==id?{...l,age:age}:l));
  };

  return (
    <>
      <ul>
        {list.map((item) => {
          return (
            <li>
              {item.name} | {item.age}
            </li>
          );
        })}
      </ul>
      <button onClick={updateAge}>Update age</button>
    </>
  );
}

4 Comments

a.age=age mutates the current state which is an anti-pattern in React.
Thats why i made the copy of the array. And setting the updated array to the list
You did a shallow copy of the array, but not the objects and you're mutating the objects.
Oh i see. Thank for the feedback. I will make the edit.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.