skip to Main Content

. I’m trying to sort the data by name and age when clicked on the header of the column. Data is getting sorted but not reflecting in the UI.
I’m sharing the code snippet,
Someone please help me out

import './App.css';
import { useState } from 'react';

function App() {
  const [names, setNames] = useState([{ name: 'John', age: 23 }, { name: 'Mary', age: 31 }, { name: 'Anna', age: 18 }, { name: 'Mark', age: 21 }])
  function sort(sortBy) {
    if (sortBy == 'name') {
      names.sort((a, b) => {
        if (a.name > b.name)
          return 1
        else return -1
      })
      setNames(names)
    } else if (sortBy == 'age') {
      names.sort((a, b) => { return b.age - a.age })
      setNames(names)
    }
  }
  return (
    <div>
      <table>
        <tr>
          <th><span style={{ cursor: 'pointer' }} onClick={() => { sort('name') }}>Name</span></th>
          <th><span style={{ cursor: 'pointer' }} onClick={() => { sort('age') }}>Age</span></th>
        </tr>
        {names.map((data) => {
          return (<tr>
            <td> {data.name}  </td>
            <td> {data.age}  </td>
          </tr>)
        })}
      </table>
    </div>
  );
}

export default App;

2

Answers


  1. You are directly modifying the names state variable, therefore React is not able to update the state since the reference to the array is going to be the same. Instead of directly modifying the names array, create a new array when updating the state variable

    function App() {
      const [names, setNames] = useState([{ name: 'John', age: 23 }, { name: 'Mary', age: 31 }, { name: 'Anna', age: 18 }, { name: 'Mark', age: 21 }])
      function sort(sortBy) {
        if (sortBy == 'name') {
          names.sort((a, b) => {
            if (a.name > b.name)
              return 1
            else return -1
          })
          setNames([...names]) // new array
        } else if (sortBy == 'age') {
          names.sort((a, b) => { return b.age - a.age })
          setNames([...names]) // new array
        }
      }
      return (
        <div>
          <table>
            <tr>
              <th><span style={{ cursor: 'pointer' }} onClick={() => { sort('name') }}>Name</span></th>
              <th><span style={{ cursor: 'pointer' }} onClick={() => { sort('age') }}>Age</span></th>
            </tr>
            {names.map((data) => {
              return (<tr>
                <td> {data.name}  </td>
                <td> {data.age}  </td>
              </tr>)
            })}
          </table>
        </div>
      );
    }
    
    export default App;
    
    Login or Signup to reply.
  2. You are doing one mistake here . Which is :

    In React, the state is immutable. In simple words it means that you should not modify it directly.

    Explanation :

    const [arr, setArr] = useState([])
    
    const handleSubmit = (event) => {
      event.preventDefault()
    
      arr.push("New Item")
      setArr(arr)
    }
    

    Why Above code didn’t work in push ?

    React determines whether the component needs to be re-rendered by comparing the prior state with the updated state. Directly changing the state will interfere with this procedure. The component will behave unexpectedly as a result. In other instances, even when the state has changed, rendering is not performed at all.

    So this can be solved as :

    import './App.css';
    import { useState } from 'react';
    
    function App() {
      const [names, setNames] = useState([
        { name: 'John', age: 23 },
        { name: 'Mary', age: 31 },
        { name: 'Anna', age: 18 },
        { name: 'Mark', age: 21 }
      ]);
    
      function sort(sortBy) {
        if (sortBy === 'name') {
          const sortedNames = [...names].sort((a, b) => {
            if (a.name > b.name) {
              return 1;
            } else {
              return -1;
            }
          });
          setNames(sortedNames);
        } else if (sortBy === 'age') {
          const sortedNames = [...names].sort((a, b) => b.age - a.age);
          setNames(sortedNames);
        }
      }
    
      return (
        <div>
          <table>
            <thead>
              <tr>
                <th>
                  <span style={{ cursor: 'pointer' }} onClick={() => sort('name')}>
                    Name
                  </span>
                </th>
                <th>
                  <span style={{ cursor: 'pointer' }} onClick={() => sort('age')}>
                    Age
                  </span>
                </th>
              </tr>
            </thead>
            <tbody>
              {names.map((data, index) => (
                <tr key={index}>
                  <td>{data.name}</td>
                  <td>{data.age}</td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>
      );
    }
    
    export default App;
    

    The spread syntax creates a copy of the array. Hence we are not modifying the original array.

    Hope this works properly. If you have any problem let me know.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search