I want to know what's the best approach to get the current state value. I figured out 2 options to reach the current value instead of getting stale value by whether using useEffect hook or using the the functional state update inside the setState function to get access to the current state.
Functional state update method
const sortbyChangeHandler = e =>
{
setSortBy(e.target.value)
setSortBy(currentSortBy =>{
if(currentSortBy === 'priceHToL'){
setProductsList(prodsCatList.sort((a,b)=>b.prodPrice - a.prodPrice))
}else if(currentSortBy === 'priceLToH'){
setProductsList(prodsCatList.sort((a,b)=>a.prodPrice - b.prodPrice))
}
else if(currentSortBy === 'qtyHToL'){
setProductsList(prodsCatList.sort((a,b)=>b.totalProdQty - a.totalProdQty))
}else if(currentSortBy === 'qtyLToH'){
setProductsList(prodsCatList.sort((a,b)=>a.totalProdQty - b.totalProdQty))
}
else if(currentSortBy === 'salesHToL'){
setProductsList(prodsCatList.sort((a,b)=>b.sales - a.sales))
}else if(currentSortBy === 'salesLToH'){
setProductsList(prodsCatList.sort((a,b)=>a.sales - b.sales))
}
});
}
This method seems like isn't the ideal one cause im using the setSortBy function twice, the first time to set update the state and the second time to Only get an access to the current state value.
beside getting a warning when I update the state.
Warning: Cannot update a component (
ProductsProvider) while rendering a different component (ProductsHeader). To locate the bad setState() call insideProductsHeader, follow the stack trace as described in
The useEffect hook method
useEffect(()=>{
if(prodsCatList.length > 0){
if(sortBy === 'priceHToL'){
setProductsList(prodsCatList.sort((a,b)=>b.prodPrice - a.prodPrice))
}else if(sortBy === 'priceLToH'){
setProductsList(prodsCatList.sort((a,b)=>a.prodPrice - b.prodPrice))
}
else if(sortBy === 'qtyHToL'){
setProductsList(prodsCatList.sort((a,b)=>b.totalProdQty - a.totalProdQty))
}else if(sortBy === 'qtyLToH'){
setProductsList(prodsCatList.sort((a,b)=>a.totalProdQty - b.totalProdQty))
}
else if(sortBy === 'salesHToL'){
setProductsList(prodsCatList.sort((a,b)=>b.sales - a.sales))
}else if(sortBy === 'salesLToH'){
setProductsList(prodsCatList.sort((a,b)=>a.sales - b.sales))
}
}
// eslint-disable-next-line react-hooks/exhaustive-deps
},[sortBy]);
This method works fine. however, it gives me a warning.
WARNING in [eslint] src\components\dashboard\Products\ProductsPageComps\ProductsHeader.jsx Line 37:7: React Hook useEffect has missing dependencies: 'prodsCatList' and 'setProductsList'. Either include them or remove the dependency array react-hooks/exhaustive-deps webpack compiled with 1 warning
that can be only ignored by using this line of code inside the useEffect.
// eslint-disable-next-line react-hooks/exhaustive-deps
Otherwise, if i tried to simply follow the esLine warning by adding both of prodsCatList and setProductsList inside the dependancy array i'll get an infinite rendering loop.
So, i was wondering which of these approaches is ideally the best practice or if there are any other approaches that would help to get me an access to the current state value.
Instead of doing anything complicated, just set a temporary variable that is the new state value and reference it throughout.
But remember,
sortupdates the array in-place, which means ifprodsCatListis a state variable (which is my assumption) you are mutating state. You'd instead want to create a new array by doing something like[...prodsCatList.sort(...)].Another note for improvement: you may not need to store the sorted list in state at all. One of React's rules for what should not go into state is "can the value be derived from state or props". Here you could simply sort the list during the render.