'Hook useFetch rerender four times

Reactjs v17, axios, react-router-dom v6.

hook useFetchAndLoad performs 4 rendering.

I know there are two renders, the first to load the component, then the useEffect. But what about the other two? Then I read that having the <React.StrictMode> renders it four times. Remove StricMode, but it still renders 4 times.

I think I have it: load the component, the useEffect, response.data, setLoading(false). There are the 4 renderings. It is right?

Question: Is it okay to render four times?

    import axios from "axios";
    import { useEffect, useState } from "react";
  
    export function useFetchAndLoad(id) {

      const [response, setResponse] = useState({});
      const [error, setError] = useState(null);
      const [loading, setLoading] = useState(false);     
      
      useEffect(() => {
        const controller = new AbortController();

        const llamarEndPoint = async () => {
          setLoading(true);     
          try {
            const response = await axios.get(`https://rickandmortyapi.com/api/character/${id}`, { signal: controller.signal });
            setResponse(response.data);
          } catch (error) {
            setError(error.message);        
          } finally {
            setLoading(false);
          }      
        }

        llamarEndPoint();

        return () => {
          setLoading(false);
          controller.abort();
        }
      }, [id]);
      console.log(response) 
      if (response ) {
        
      }

      return { loading, response, error };
    }
    import React, { 
    } from 'react'
    import { 
      Link,
      Outlet, 
      useLocation,
    } from 'react-router-dom';


    const RickAndMorty = () => {

      const location = useLocation();
      console.log(location);
      // console.log("4 Links")
      return (
        <div>
          <h1>Rick and Morty</h1>
        
          <ul>
            <li><Link to="1">Rick</Link></li>
            <li><Link to="2">Morty</Link></li>
            <li><Link to="3">3otro</Link></li>
            <li><Link to="4">4otro</Link></li>
          </ul>
          
          <article>
            <Outlet />
          </article>

        </div>
      )
    }

    export default RickAndMorty
    import {useParams} from 'react-router-dom';
    import { useFetchAndLoad } from '../../hook/useFetchAndLoad';

    const Api = () => {

      const params = useParams();
      const id = parseInt(params.id);
      
      const { loading, response, error } = useFetchAndLoad(id);
     
      return (
        <article>
          <h1>Api</h1>
          {loading ? <p>Loading...</p> : response.name ?? error}
     
        </article>
      )
    }

    export default Api; 
useFetchAndLoad.js:36 {}
useFetchAndLoad.js:36 {}
useFetchAndLoad.js:36 {id: 2, name: 'Morty Smith'}
useFetchAndLoad.js:36 {id: 2, name: 'Morty Smith'}


Solution 1:[1]

You're not logging loading, but my crystal ball's best guess is that if you were, you'd see

useFetchAndLoad.js:36 loading = false {}
useFetchAndLoad.js:36 loading = true {}
useFetchAndLoad.js:36 loading = true {id: 2, name: 'Morty Smith'}
useFetchAndLoad.js:36 loading = false {id: 2, name: 'Morty Smith'}

so yes, everything's quite correct.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 AKX