Home > OS >  Function doesn't wait react hooks
Function doesn't wait react hooks

Time:12-01

I'm trying to add items in shopping cart. It works, but after adding items when I want to calculate number of items to show on the shopping cart. Second function (calculate()) doesn't wait items hooks. Because of that, it shows the correct count after adding second item.

Below code is my functions. As you can see, in the end of first function I'm calling the calculate() function to keep it continue.

const [testArray, setTestArray] = useState([]);
const [total, setTotal] = useState(0);
const [cartCount, setCartCount] = useState(0);

function addToTest(product, quantity = 1) {
    const ProductExist = testArray.find((item) => item.id === product.id);
    if (ProductExist) {
      setTestArray(
        testArray.map((item) => {
          if (item.id === product.id) {
            return { ...ProductExist, quantity: ProductExist.quantity   1 };
          } else {
            return item;
          }
        })
      );
    } else {
      product.quantity = 1;
      setTestArray([...testArray, product]);
    }

    calculate();
  }
  

  function calculate() {
    let resultCount = 0;
    testArray.map((item) => {
      console.log("map func works!");
      setCartCount(cartCount   item.quantity);
    });
  }

Here is my codesandbox project, I kept it very simple to not bother you.

https://codesandbox.io/s/react-template-forked-u95qt?file=/src/App.js

The possible problem occurs due to synchronise functions. Because of that, when I try to async/await, I'm getting error about parameters, because the first function has parameter.

This is my first try for async/await:

async function calculate(product) {
    await addToTest(product);
    let resultCount = 0;
    testArray.map((item) => {
      console.log("map func works!");
      setCartCount(cartCount   item.quantity);
    });
  }

As other solution I tried to use useEffect by taking the reference setArray hooks. However, in this case, the count number increases exponentially like 1,3,9...

useEffect(()=>{
    let resultCount = 0;
    testArray.map((item) => {
      console.log("map func works!");
      setCartCount(cartCount   item.quantity);
    });
  },[testArray])

I wonder where is the problem? Because when I use the the upper code in Angular/Typescript, it works properly. I think this happens due to react hooks, but I couldn't understand the problem.

CodePudding user response:

Every call to setCartCount will only update cartCount on the next render, so you are (effectively) only calling it with the final item in the array. You should instead use reduce on the array to get the value you want, and then set it.

See https://codesandbox.io/s/react-template-forked-u95qt?file=/src/App.js

CodePudding user response:

Your thought to use a useEffect is a good one, but instead of calling setCartCount on every iteration you should instead sum all the item.quantity counts first and then call setCartCount once after your loop.

Note: don't use map() if you're going to ignore the array it returns, use a for loop, for...of as in the example below, or forEach() instead.

useEffect(() => {
  let resultCount = 0;
  for (const item of testArray) {
    resultCount  = item.quantity;
  }

  setCartCount(resultCount);
}, [testArray]);

or with reduce() (here destructuring and renaming the quantity property of each passed item)

useEffect(() => {
  const resultCount = testArray.reduce((a, { quantity: q }) => a   q, 0);

  setCartCount(resultCount);
}, [testArray]);
  • Related