How can I use useMemo dependent on the webapi

Viewed 34

I have a webapi invoked that is working properly:

const [pItem, setPItem] = useState([]);
const [weight, setWeight] = useReducer(weightHandler, 0.0);
useEffect(() => {
    setLoading(true);
    let mounted = true;
    (async function () {
        await getPlantInfoById(itemId)
            .then(item => {
                if (mounted) {
                    setPItem(item)
                    setLoading(false);
                }
            })
    })();
    return () => { mounted = false; }
}, [itemId])

Here pItem contains data now I have another filled called weight(which can be changed by a user) .

So I need some calculations according to the weight changes:

const PaymentCalculator = function () {
    const [item] = [...pItem];
    const priceWithDiscount = DiscountCalc(item.price, item.discount);
    const divideWeight = weight / item.weight;
    const result = (divideWeight * priceWithDiscount) * 1000;

    return result;
}
const use = useMemo(() => PaymentCalculator(), [weight])

But it seems PaymentCalculator invoked before useEffect !!

How can I fix this?

1 Answers

If you examine the contents of paymentCalculator you'll see you've more than just weight as a dependency.

const PaymentCalculator = function () {
  const [item] = [...pItem];
  const priceWithDiscount = DiscountCalc(item.price, item.discount);
  const divideWeight = weight / item.weight;
  const result = (divideWeight * priceWithDiscount) * 1000;

  return result;
}

pItem is also a dependency!

Initially pItem is an empty array, and since all hooks are called on each render cycle, this would mean that item is undefined on the initial render and accessing item.price and item.discount will throw an error for attempting to "access X of undefined".

Add pItem to the dependency array and provide a fallback value.

const paymentCalculator = function() {
  const [item = {}] = [...pItem];

  const priceWithDiscount = discountCalc(item.price, item.discount);
  const divideWeight = weight / item.weight;
  const result = (divideWeight * priceWithDiscount) * 1000;

  return result;
}

...

const use = useMemo(() => PaymentCalculator(), [pItem, weight]);
Related