Eiron
Eiron

Reputation: 1

Fetching too many times

Im creating a side project for fun in react with create-react-app. I created a hook thats supposed to fetch some information in json and it does the job, the problem is that for some reason its sending a request per item in the json and this is a json with 700+ items, is it a re-render situation? Is it because I'm not using useEffect?


export const useFetchQL = (url: URL): Array<Object> => {
    const [data, setData] = useState([]);

    const getData = async () => {
        let query = `
        query {
          characters{
            id 
            name 
            title 
            imageURL 
            leaderSkill 
            passive 
            categories 
            links
          }
        }`;
        let response = await fetch(url,{
            method: "POST",
            headers: {
                "Content-Type": "application/json",
                "Accept": "application/json"
            },
            body: JSON.stringify({query}),
        })
        let data = await response.json();
        setData(data.data.characters)
    }
    getData();  
    return data;
}

I tried calling it in different parts of the project and nothing, same output. What's happening here and how do I avoid it?

I only need/want to fetch this information once so I can start using it. I would like to post IMG but I cant.

import './App.css';
import Cards from './components/Cards';
import Team from './components/Team';
import Search from './components/Search';
import { AddToTeamProvider } from './context/addToTeamContext';
import { useState } from 'react';
import { useFetchQL } from './hooks/useFetchQL.ts';

function App() {
  const [chars, setChars] = useState([]);
  setChars(useFetchQL('https://dokkanapi.azurewebsites.net/graphql'));
  console.log(chars);
  return (
    <div className="App">
      <AddToTeamProvider>
        <Team/>
        <Search/>
        <Cards/>
      </AddToTeamProvider>
    </div>
  );
}

export default App;

Upvotes: 0

Views: 512

Answers (2)

Mario Petrovic
Mario Petrovic

Reputation: 8332

First of all this is not the way you should write hook and use them. This is more a regular function that returns data after API is finished. You tried to combine API hook pattern with regular function.

Also you are calling it in the main render flow and it will call it many times since you are setting state every time component rerenders.

Here is the one example how you can do this:

export const getQL = async (url: URL): Array<Object> => {
  let query = `
        query {
          characters{
            id 
            name 
            title 
            imageURL 
            leaderSkill 
            passive 
            categories 
            links
          }
        }`;
  let response = await fetch(url, {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      Accept: "application/json",
    },
    body: JSON.stringify({ query }),
  });

  return response.json();
};

And than use this method in a useEffect in your component:

import "./App.css";
import Cards from "./components/Cards";
import Team from "./components/Team";
import Search from "./components/Search";
import { AddToTeamProvider } from "./context/addToTeamContext";
import { useState } from "react";
import { getQL } from "./hooks/useFetchQL.ts";

function App() {
  const [chars, setChars] = useState([]);

  useEffect(() => {
    const call = async () => {
      const result = await getQL("https://dokkanapi.azurewebsites.net/graphql");

      setChars(result);
    };

    call();
  }, []);

  return (
    <div className="App">
      <AddToTeamProvider>
        <Team />
        <Search />
        <Cards />
      </AddToTeamProvider>
    </div>
  );
}

export default App;

Upvotes: 3

IRadics
IRadics

Reputation: 21

You need to put your getData() in useEffect hook with an empty dependency array to only run it run once (or alternatively with the "url" prop, which should refetch once you change the url prop in the parent component)

Upvotes: -1

Related Questions