简体   繁体   中英

How to fix fetch and render issue in React?

I have spent two days trying to figure out what's going on and still can't figure out where the issue is. It's so frustrating:((

I have this code on code sandbox fetching from an api the month and total then doing simple calculations.

https://codesandbox.io/s/agitated-cdn-q3gju?file=/src/Card.js

The first issue: With every other page refresh, the value on screen will first render the first total then on the second refresh, it will render the second total. (please see the code on sandbox to understand better what I mean)

The second issue: when I try to console.log the revenue I get the array printed on the console twice, not sure why it's fetching it twice.

The third issue: I understand that it might be something to do with my backend code (which I'm including a snippet below) but I really have gone through each line to debug and can't spot the mistake.

Your help is so much appreciated

router.get("/incomestats", verifyTokenAndAdmin, async (req, res) => {
  const date = new Date();
  const lastMonth = new Date(date.setMonth(date.getMonth() - 1));
  const previousMonth = new Date(date.setMonth(lastMonth.getMonth() - 1));
  // const previousMonth =  new Date(new Date().setMonth(lastMonth.getMonth() - 1));
  try {
    const ordersData = await Order.aggregate([
      { $match: { createdAt: { $gte: previousMonth } } },
      { $project: { month: { $month: "$createdAt" }, sales: "$amount" } },
      { $group: { _id: "$month", total: { $sum: "$sales" } } },
    ]);
    res.status(200).json(ordersData);
  } catch (error) {
    res.status(500).json(error);
    console.log(error);
  }
});

The primary issues is with the dependency array that you passed into your useEffect call.

useEffect(() => {
  const getRevenue = async () => {
    try {
      const res = ...;
      setRevenue(res.data);
      setDifference((res.data[1].total * 100) / (res.data[0].total - 100));
    } catch (error) {
      ...
    }
  };
  getRevenue();
}, [difference]);

You have [difference] when it should be [setRevenue, setDifference] . By including difference you are telling react that it needs to run this effect when difference changes HOWEVER you are also calling setDifference here which changes the value of difference . This will infinitely loop. Changing the dependencies to [setRevenue, setDifference] will resolve the infinite loop problem.

useEffect(() => {
  const getRevenue = async () => {
    try {
      const res = ...;
      setRevenue(res.data);
      setDifference((res.data[1].total * 100) / (res.data[0].total - 100));
    } catch (error) {
      ...
    }
  };
  getRevenue();
}, [setRevenue, setDifference]);

The second thing (which debatably isn't even an issue) is that inside useEffect you are calling setRevenue and setDifference in an asynchronous context. In versions of React before the new beta version (18) react doesn't batch these two state updates. This question explains it really well imo.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM