Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

functional component not re-rendering after setState update hook

I have the below component which I thought would be super simple. The data is passed into a child component that renders a bar chart using charts.js. On the first render everything works fine. However, when I run the 'sort data' function, the data is updated but the child component doesn't re-render. Seen similar problems with class based components but can't find the answer for my case.

import React, { useState } from 'react';

const Landing = () => {

    const [data, setData] = useState([
        { year: 2017, value: 50 },
        { year: 2016, value: 60 },
        { year: 2013, value: 50 },
        { year: 2014, value: 80 },
        { year: 2019, value: 70 }

    ]);


    const sortData = () => {
        const newArray = data.sort(function (a, b) { return a.year - b.year })
        setData(newArray);
    }

    return (
        <div>
            <BarChart data={data} />
            <button onClick={sortData} > sort data </button>
        </div>

    )
}

export default Landing
like image 761
Sam Henderson Avatar asked Aug 09 '26 09:08

Sam Henderson


1 Answers

The reason why your component doesn't re-render is because you're directly mutating your state when you use data.sort and according to React docs, you should

Never mutate state directly, as calling setState() afterwards may replace the mutation you made. Treat state as if it were immutable.

  • reactjs.org/docs/react-component.html#state

Since Array.sort method is mutable, you should create a copy of data and then use Array.sort on the new array.

const Landing = () => {
  const [data, setData] = React.useState([
    { year: 2017, value: 50 },
    { year: 2016, value: 60 },
    { year: 2013, value: 50 },
    { year: 2014, value: 80 },
    { year: 2019, value: 70 }
  ]);

  const sortData = () => {
    // using `spread operator` to create
    // a copy of the `data` array
    const newArray = [...data].sort(function(a, b) {
      return a.year - b.year;
    });
    setData(newArray);
  };

  return (
    <div>
      <BarChart data={data} />
      <button onClick={sortData}> sort data </button>
    </div>
  );
};

If an array method mutates the original array, always make a copy of your array before updating your state.

Have a look here to see which Array methods are mutable and which ones are not:

  • doesitmutate.xyz
like image 169
goto Avatar answered Aug 10 '26 21:08

goto



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!