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
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
statedirectly, as calling setState() afterwards may replace the mutation you made. Treatstateas if it were immutable.
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:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With