I have a useState as following:
const [drivers, setDrivers] = useState(useSelector(selectFilteredDrivers));
Here drivers is an array we can map through.
I have a sorting function that sorts the list of drivers:
const sortDrivers = useCallback(
(sortBy: string) => {
const sortFunction = (
a: DeliveryDriver,
b: DeliveryDriver,
sort: string,
) => {
if (sortBy === 'desc') {
return Number(a.isAvailable) - Number(b.isAvailable);
} else {
return Number(b.isAvailable) - Number(a.isAvailable);
}
};
const sortedListOfDrivers = drivers.sort((a, b) =>
sortFunction(a, b, sortBy),
);
console.log('sortedList', sortedListOfDrivers);
setDrivers(sortedListOfDrivers);
},
[drivers],
);
As you can see I sort the list and set the list to sortedListOfDrivers. Down below I map through drivers list to return Driver component for each driver:
const rows = drivers.map(driver => (
<Driver
driver={driver}
key={driver.driverId}
handleRowOnClick={driverDetailClickHandler}
/>
));
If you are wondering, rows is something I pass to Table component as a prop.
render (
<Table headers={headers} rows={rows} />
)
The function is passed down as a callback and attached to onClick.
When I console.log drivers after sorting, it shows that array of drivers is updated accordingly after click, so sorting functionality works great behind the scenes.
The problem is that in UI my list remains the same (like before sorting) and it doesn't re-render the list to make it sorted after the click.
NOTE: Not sure if it has to do something with the issue, but for some reason, UI refreshes to show sorted list when I start typing something in input field which has nothing to do with the sorting function.
How do I make it update the list of drivers when function is executed (button clicked)?
I've tried placing my mapping part in useEffect(). It didn't work.
Any suggestion is appreciated.
CodePudding user response:
The sort() method sorts the elements of an array in place and returns the sorted array. The default sort order is ascending, built upon converting the elements into strings, then comparing their sequences of UTF-16 code units values.
It means that sortedListOfDrivers === drivers
is true
and setDrivers
thinks that nothing changed. You should create a new array to avoid that:
setDrivers([...sortedListOfDrivers]);
Note: drivers.sort
changes the variable without notifying react. So it doesn't update your UI until something other triggers a rerender.