Reputation:
I have React app and I am using React hooks:
const [companies, setCompanies] = useState([]);
I am fetching the data and 'companies' is getting filled with data. I also have another button for sorting the data by NetIncome:
const sortByIncome = e => {
const el = document.getElementById("sort-selectbox");
const arr = companies.sort((a, b) => (a.NetIncome > b.NetIncome ? -1 : 1));
console.log(arr);
setCompanies(arr);
};
The problem is that setCompanies does not re-renders. In the console.log I can see that array is sorted correctly and even if I console.log(companies) I can see that it is also sorted. But noting happens in the interface. Also if I type the same code:
const sortByIncome = e => {
const el = document.getElementById("sort-selectbox");
const arr = companies.sort((a, b) => (a.NetIncome > b.NetIncome ? -1 : 1));
console.log(arr);
setCompanies([]);
};
but pass to setCompanies empty array it immediately works and displays nothing (I have render function that gets companies as param). So why it is not working with passing arr? Is it because I am passing the same array but just sorted?
Upvotes: 7
Views: 2552
Reputation:
The value of the hook-variable companies
inside the function sortByIncome
will always be the initial value of your hook ([]
) and will never receive the new value set by using setCompanies
.
A solution to your problem is to wrap your function sortByIncome
in a useCallback
hook with the hook-variable companies
as a dependency. This will ensure that the function always uses the current value of companies
.
const sortByIncome = React.useCallback(e => {
// Using `companies` will always result in the current value
}, [companies]);
Upvotes: 0
Reputation: 14669
Here:
const arr = companies.sort((a, b) => //...
Array.prototype.sort
sorts array in place, that is, mutates the original object. The reference doesn't change, and the mutation doesn't get noticed. Do instead
const arr = [...companies].sort((a, b) => //...
Upvotes: 12