skip to Main Content

First of all I will say with React Im a begginer and what I really dont understand is why I cannot fetch 2 endpoints, so they retrieve me data and then I can use it in my differents components

This is my App.jsx

import { Route, Routes } from 'react-router-dom';
import useFetch from './hooks/useFetch';
import { BlogContentPage, Homepage } from './pages';
import AboutPage from './pages/AboutPage';

export default function App() {
  let { loading, data, error } = useFetch('http://localhost:1337/api/blogs?populate=*'); // this one is ok, is recieving data.
  let { data: authors } = useFetch('http://localhost:1337/api/authors?populate=*'); // this one is not, and if I remove the one above this one works (!?!?!)
  if (loading) return <p>Loading...</p>;
  if (error) return <p>Error!</p>;
  console.log(authors); // this is null..
  return (
    <div>
      <Routes>
        <Route path='/' element={<Homepage blogs={data ? data : ''} />}></Route>
        <Route path='/blog/:id' element={<BlogContentPage blogs={data ? data : ''} />}></Route>
        <Route path='/about' element={<AboutPage authors={authors ? authors : ''} />}></Route>
      </Routes>
    </div>
  );
}

This is my useFetch custom Hook (and probably I’m doing something wrong here)..

import { useEffect, useState } from 'react';

const useFetch = (url) => {
  const [data, setData] = useState(null);
  const [error, setError] = useState(null);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    const fetchData = async () => {
      setLoading(true);
      try {
        const res = await fetch(url);
        const json = await res.json();
        setData(json);
        setLoading(false);
      } catch (error) {
        setError(error);
        setLoading(false);
      }
    };
    fetchData();
  }, [url]);

  return { loading, error, data };
};

export default useFetch;

My expectation was that the useFetch hook that I wrote work everytime it gets call.

2

Answers


  1. Well you could just refactor you custom hook to accept multiple endpoints

    import { useEffect, useState } from 'react';
    
    const useFetch = (urls) => {
      const [data, setData] = useState([]);
      const [error, setError] = useState(null);
      const [loading, setLoading] = useState(true);
    
      useEffect(() => {
        const fetchData = async () => {
          setLoading(true);
          try {
            const promises = urls.map(async (url) => {
              const res = await fetch(url);
              return res.json();
            });
            const results = await Promise.all(promises);
            setData(results);
            setLoading(false);
          } catch (error) {
            setError(error);
            setLoading(false);
          }
        };
        fetchData();
      }, [urls]);
    
      return { loading, error, data };
    };
    
    export default useFetch;
    

    And in your main file you can use it this way

      const { loading, data: blogData, error } = useFetch(['http://localhost:1337/api/blogs?populate=*', 'http://localhost:1337/api/authors?populate=*']);
    
      if (loading) return <p>Loading...</p>;
      if (error) return <p>Error!</p>;
    
    Login or Signup to reply.
  2. Try to pass the first loading value, to the other fetch hook:

    let { loading, data, error } = useFetch('http://localhost:1337/api/blogs?populate=*', false) <-- also add this
    let { data: authors } = useFetch('http://localhost:1337/api/authors?populate=*', loading) // <-- from the first useFetch hook
    

    and then inside the useFetch hook:

     useEffect(() => {if (!loading) {
    const fetchAuthors = async () => {
      const { data: authorsData } = await useFetch('http://localhost:1337/api/authors?populate=*');
      setAuthors(authorsData);
    };
    fetchAuthors();}}, [loading,url]);
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search