Best approach to get the current state value

60 Views Asked by At

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 inside ProductsHeader, 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.

1

There are 1 best solutions below

1
Brian Thompson On BEST ANSWER

Instead of doing anything complicated, just set a temporary variable that is the new state value and reference it throughout.

const sortbyChangeHandler = e => {
  const newSortBy = e.target.value;
  setSortBy(newSortBy)

  if(newSortBy === 'priceHToL'){
      setProductsList(prodsCatList.sort((a,b)=>b.prodPrice - a.prodPrice))
  } else if (newSortBy === 'priceLToH') {
      setProductsList(prodsCatList.sort((a,b)=>a.prodPrice - b.prodPrice))
  } else if (newSortBy === 'qtyHToL') {
      setProductsList(prodsCatList.sort((a,b)=>b.totalProdQty - a.totalProdQty))
  } else if (newSortBy === 'qtyLToH') {
      setProductsList(prodsCatList.sort((a,b)=>a.totalProdQty - b.totalProdQty))
  } else if (newSortBy === 'salesHToL') {
      setProductsList(prodsCatList.sort((a,b)=>b.sales - a.sales))
  } else if (newSortBy === 'salesLToH') {
      setProductsList(prodsCatList.sort((a,b)=>a.sales - b.sales))
  }
}

But remember, sort updates the array in-place, which means if prodsCatList is 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.