Skip to content
Advertisement

Why to use Object.assign() to update functional component props change?

I have a list of students and I display them on the table. There are two buttons that indicate by which value should I sort the list (name or birthdate). When the button is clicked and I sort the list, the list itself is getting sorted, but it’s not updating if I don’t assign the list to the new list using Object.assign(newList, oldList) and then update it by passing to the update state function updateList(newList). Here’s my code:

const students= [
  {
    name: "John Done",
    year: 1,
    birthdate: "2020-01-24",
  },
  {
    name: "Another Done",
    year: 3,
    birthdate: "2002-02-20",
  },
  {
    name: "Jack London",
    year: 2,
    birthdate: "1800-01-04",
  },
  {
    name: "Text Name",
    year: 3,
    birthdate: "1990-02-24",
  },
  {
    name: "Name",
    year: 2,
    birthdate: "2005-04-01",
  },
];

ReactDOM.render(<App students={students} />, document.getElementById('root'));

function App({ students }) {
  const [studentsList, setStudentsList] = useState(students);

  const sortByYear = () => {
    // let sortedstudents = [];
    // Object.assign(sortedStudents, studentsList);
    // sorteStudents.sort((a, b) => b.year - a.year);
    // console.log(sorteStudents);
    // setStudentsList(sortedStudents);
    studentsList.sort((a,b) => b.year - a.year));
    setStudentsList(studentsList);
  };

const sortByDates = () => {
  // let sortedStudents = [];
  // Object.assign(sortedStudents, studentsList);
  // sortedStudents.sort((a, b) => new Date(b.birthdate) - new Date(a.birthdate));
  // console.log(sortedStudents);
  // setStudentsList(sortedStudents);
  studentsList.sort((a, b) => new Date(b.birthdate) - new Date(a.birthdate));
  setStudentsList(studentsList);
};

return (
<div className="App">
  <div>
    <label>
      Sort By
    </label>
    <button
      onClick={() => sortByYear()}
    >
      Year
    </button>
    <button
      onClick={() => sortByDates()}
    >
      Most Old
    </button>
  </div>
  <Students students={studentsList} />
</div>
 );
}

Students component

function Students({ students }) {
return (
    <div>
      <table>
        <thead>
          <tr>
            <th>Name</th>
            <th>Year</th>
            <th>Date of birth</th>
          </tr>
        </thead>
        <tbody>
          {students.map((student, index) => (
            <tr key={index}>
              <td>{student.name}</td>
              <td>{student.year.toString()}</td>
              <td>{student.birthdate}</td>
            </tr>
          ))}
        </tbody>
      </table>
    </div>
  );
}

So here in this way even though the students’ list is getting sorted, the state is not updating, but if I assign the initial list to the new one and then sort it and then update the state it is working.

WORKS

let sortedStudents = [];
Object.assign(sortedStudents, studentsList);
sortedStudents.sort((a, b) => new Date(b.birthdate) - new Date(a.birthdate));
//console.log(sortedStudents);
setStudentsList(sortedStudents)

DOES NOT WORK

studentsList.sort((a, b) => new Date(b.birthdate) - new Date(a.birthdate));
setStudentsList(studentsList);

So the question is why do I need to assign my studentsList to the new array, specifically by using Object.assign() so that setStudentsList() would update the component’s state? I’ve just started learning React so it’s really confusing me the way how these states actually work.

Similar posts I’ve found

Advertisement

Answer

As Brain mentioned: React determines if it should re-render or not based on the equality of previous props to the next props, and previous state to the next state. By mutating the original state array, the previous studentList has referential equality with the updated studentList and react will not detect that it needs to rerender.

So in order to change the list and to React detect the changes, the value of the array needs to be used (mutated), instead of its reference.

As Bergi hinted: alternative that copies the array by value

User contributions licensed under: CC BY-SA
9 People found this is helpful
Advertisement