Home > Enterprise >  why does sorting in setSomething function of useState hook does not work?
why does sorting in setSomething function of useState hook does not work?

Time:03-20

I have 2 components. One is App component and other one is NumbersList component. The NumbersList is a child component of the App component. The App component receives a list of numbers called lst as a prop. The App component has 2 buttons sort Ascending and sort Descending and they try to do what the name implies.

The app component:

import React, { useState } from 'react';
import './style.css';
import NumbersList from './NumbersList';

export default function App({ lst }) {
  const [sortedLst, setSortedLst] = useState(lst);
  function sortAscHandler() {
    setSortedLst((prev) => prev.sort((a, b) => a - b));
  }
  function sortDescHandler() {
    setSortedLst((prev) => prev.sort((a, b) => b - a));
  }
  return (
    <div>
      <button onClick={sortAscHandler}>Sort Ascending</button>
      <button onClick={sortDescHandler}>Sort Descending</button>
      <NumbersList lst={sortedLst} />
    </div>
  );
}

The NumbersList component:

import React from 'react';

const NumbersList = ({ lst }) => {
  return (
    <ul>
      {lst.map((num) => (
        <li>{num}</li>
      ))}
    </ul>
  );
};

export default NumbersList;

The main index.js file:

import React from 'react';
import ReactDOM from 'react-dom';

import App from './App';
const lst = [4, 3, 2, 1, 7, 6, 5, 100, 9, 8];

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

The problem is the the when the buttons are clicked, the sortedLst is not updated in the view.

stackblitz-link: https://stackblitz.com/edit/react-jyqeuy?file=src/index.js

Thank you in advance

CodePudding user response:

Array.prototype.sort is an in-place sort. In other words, it mutates the array it operates on and doesn't return a new array reference.

Array.prototype.sort

The sort() method sorts the elements of an array in place and returns the sorted array.

Make a shallow copy first, then sort the new array reference.

export default function App({ lst }) {
  const [sortedLst, setSortedLst] = useState(lst);
  function sortAscHandler() {
    setSortedLst((prev) => prev.slice().sort((a, b) => a - b));
  }
  function sortDescHandler() {
    setSortedLst((prev) => prev.slice().sort((a, b) => b - a));
  }
  return (
    <div>
      <button onClick={sortAscHandler}>Sort Ascending</button>
      <button onClick={sortDescHandler}>Sort Descending</button>
      <NumbersList lst={sortedLst} />
    </div>
  );
}
  • Related