PHPFixing
  • Privacy Policy
  • TOS
  • Ask Question
  • Contact Us
  • Home
  • PHP
  • Programming
  • SQL Injection
  • Web3.0

Thursday, October 13, 2022

[FIXED] Why my component is rendering 4x times even with useCallback and useEffect?

 October 13, 2022     axios, react-hooks, reactjs     No comments   

Issue

I'm a beginner in React and I'm trying to fetch data using Axios.

This fetching is being controlled by useState (loading, errors, getting data) and useEffect/useCallback.

My code has a console.log("hey") just to show me when the component is being rendered.

import { useCallback } from "react";
import { useState, useEffect } from "react";
import DriversList from "./components/DriversList";
import axios from "axios";

function App() {
  const [drivers, setDrivers] = useState([]);
  const [isLoading, setIsLoading] = useState(false);
  const [error, setError] = useState(null);

  const apiGetDataHandler = useCallback(() => {
    setIsLoading(true);
    setError(null);

    axios
      .get("http://ergast.com/api/f1/2022/drivers.json?limit=25")
      .then((response) => {
        setIsLoading(false);
        setDrivers(response.data.MRData.DriverTable.Drivers);
      })
      .catch((error) => {
        setError(error.message);
      });
  }, []);

  useEffect(() => {
    apiGetDataHandler();
  }, [apiGetDataHandler]);

  let content = <DriversList drivers={drivers} />;
  console.log("hey");

  if (error) {
    content = <p>{error}</p>;
  }

  if (isLoading) {
    content = <p>Loading...</p>;
  }

  return (
    <>
      <section>{content}</section>
    </>
  );
}

export default App;

Solution

Assuming react 18 and <StrictMode>, here's the 4 renders:

The component mounts, and that's render #1

After the first render, the effect runs and you call setIsLoading(true) and setError(null). Since loading changed from false to true, this results in render #2. Also, the axios.get is kicked off.

Because of strict mode, react simulates unmounting/remounting the component, and runs your effect again. The calls to setIsLoading and setError won't actually cause another render, because the new values are the same as the old values, but the effect does kick off an additional call to axios.get

Some time later, one of the axios.gets finishes. You call setIsLoading(false) and setDrivers(response.data.MRData.DriverTable.Drivers). Both of these result in changes, which are batched up into a single render #3.

Some time later, the second axios.get finishes. You call setIsLoading(false) and setDrivers(response.data.MRData.DriverTable.Drivers). The loading part doesn't change anything, but the drivers does change, resulting in render #4.


You can eliminate 1 render by having isLoading start off as true. That way, when you call setIsLoading(true) right after mount, nothing changes.

const [isLoading, setIsLoading] = useState(true);

You can eliminate another render by having your useEffect return a teardown function which stops the fetch when the component unmounts. You could either cancel the fetch entirely via an axios abort controller, or just set a variable reminding you to not set the state when it finishes. Also, if you move the function into the effect, you won't need to use useCallback:

useEffect(() => {
  let cancelled = false;

  setIsLoading(true);
  setError(null);

  axios
    .get("http://ergast.com/api/f1/2022/drivers.json?limit=25")
    .then((response) => {
      if (cancelled) {
        return;
      }
      setIsLoading(false);
      setDrivers(response.data.MRData.DriverTable.Drivers);
    })
    .catch((error) => {
      if (cancelled) {
        return;
      }
      setError(error.message);
    });

  return () => {
    cancelled = true;
  } 
}, []);


Answered By - Nicholas Tower
Answer Checked By - Marilyn (PHPFixing Volunteer)
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg
Newer Post Older Post Home

0 Comments:

Post a Comment

Note: Only a member of this blog may post a comment.

Total Pageviews

Featured Post

Why Learn PHP Programming

Why Learn PHP Programming A widely-used open source scripting language PHP is one of the most popular programming languages in the world. It...

Subscribe To

Posts
Atom
Posts
Comments
Atom
Comments

Copyright © PHPFixing