1

I created an array of objects with properties of name and birth_date. I then create a Person component and map out the array using props. I'd like to make the name editable so I put the props into an input value. I am trying to use hooks to be able to update that objects name, however, what I currently have only returns an empty value and then edits all values in the table. Any way to specify to only edit that particular objects name and update the array?

NewTable.js

import React, { useState } from 'react';
import './list.css';
import TableHeader from './TableHeader';
import PersonItem from './PersonItem';
import { people } from './people.js';


function NewTable() {

  const [itemDetails, editItemDetails] = useState(people.name)

  function newPeople(people) {
    return (
      <PersonItem
        name={itemDetails}
        date={people.birth_date}
        edit={e => editItemDetails(e.target.value)}
      />
    );
  }

  return(
    <div id="task-group">
      <table className="task-list">
        <TableHeader />
        <tbody>
          {people.map(newPeople)}
        </tbody>
      </table>
    </div>
  )
}

export default NewTable;

PersonItem.js

import React from 'react';
import './list.css';

function PersonItem(props) {

  return(
      <tr>
        <td><input type="text" value={props.name} onChange={props.edit}/></td>
        <td><input type="text" value={props.date}/></td>
      </tr>
  )
}

export default PersonItem;

people.js

const people = [
  {
    name: "John Smith",
    birth_date: '01/01/1991',
  },
  {
    name: "Dwayne Johnson",
    birth_date: '03/05/1992',
  },

]

export { people };
1
  • const [itemDetails, editItemDetails] = useState(people.name). people does not have a name, people is an array. Commented Feb 10, 2021 at 17:36

2 Answers 2

1

Here is one possible solution:

Have a unique id for every person:

const myPeople = [
  {

    id: "1",
    name: "John Smith",
    birth_date: '01/01/1991',
  },
  {
    id: "2",
    name: "Dwayne Johnson",
    birth_date: '03/05/1992',
  },
]

Then pass down this function to the PersonItem component so they can call up and change the state:

const [people, setPeople] = useState(myPeople)

// Pass this function as a prop to PersonItem
function changeNameOfPerson(id, newName) {
  const peopleCopy = [...people];
  for (let person in peopleCopy) {
    if (person.id === id) {
      person.name = newName;
    }
  }
  setPeople(peopleCopy);
}
Sign up to request clarification or add additional context in comments.

6 Comments

Thanks, this is really helpful! I added this but, I'm still getting this error: Warning: You provided a value prop to a form field without an onChange handler. This will render a read-only field. If the field should be mutable use defaultValue. Otherwise, set either onChange or readOnly.
Would be useful to show your current work on codesandbox. Easier to spot the issue then :)
Definitely! Here is the codesandbox.io/s/people-sandbox-qn1un :)
Check the PersonItem component. You have to call the function with id and the new value for the the name. And also pass in the id as a prop to the component so it's accessible there :) The foor loop had a small mistake where I was using "in" istead of "of".
|
1

A good practice when using hooks is to name the function that changes the state with the prefix 'set'. Example: [nameOfYourVar, setNameOfYourVar] This improves the readability.

Like Mellet said, it's important to use an unique identifier on each object. you can use this id to change an specific object from your array. Source

1 Comment

Thank you! This is really helpful knowledge!

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.