Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

237
Visualizações
React: Custom Fetch Hook with or without useCallback?

I am currently teaching myself React, and have stumbled upon the following code snipped for a custom hook that uses the fetch() method.

import { useState, useEffect, useCallback } from "react";
import axios from "axios";

function useFetch(query, page) {
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(false);
  const [list, setList] = useState([]);

  const sendQuery = useCallback(async () => {
    try {
      await setLoading(true);
      await setError(false);
      const res = await axios.get(url);
      await setList((prev) => [...prev, ...res.data];
      setLoading(false);
    } catch (err) {
      setError(err);
    }
  }, [query, page]);

  useEffect(() => {
    sendQuery(query);
  }, [query, sendQuery, page]);

  return { loading, error, list };
}

export default useFetch;

I can't quite understand the use of useCallback() in this context. My fetch() hooks so far only imported useState() and useEffect() and then called useEffect() whenever one of the parameters changed. Can somebody explain to me what exactly useCallback() does and when I should use it to fetch data from an API?

about 4 years ago · Juan Pablo Isaza
3 Respostas
Responde à pergunta

0

I think I have found the problem: If you have a component, and a function that handles user input by calling the API (using the hook) with the current value whenever it changes, this inner function is re-created whenever the component re-renders, which happens every time anything inside it changes. This means that when anything else inside the component changes, the API is called again.

This problem can be solved by wrapping the API call into the useCallback() hook and passing it the input value as a dependency, so that the API is only called when the input changes, and the last response is memoized between re-renders of the component.

I have found a video that is a great explanation.

about 4 years ago · Juan Pablo Isaza Relatório

0

According to offical doc: https://reactjs.org/docs/hooks-reference.html#usecallback.
UseCallback will return a memoized version of the callback that only changes if one of the dependencies has changed. This is useful when passing callbacks to optimized child components that rely on reference equality to prevent unnecessary renders

So, in your case, It's not using the memoized version for children, but it uses to the useEffect so the useEffect will triggered when query or page changes, to be honest, it doesn't have to be this way, for me this is a bit over-engineered, you could also do it something like this:

useEffect(async () => {
  try {
    await setLoading(true);
    await setError(false);
    const re
s = await axios.get(url);
    await setList((prev) => [...prev, ...res.data];
    setLoading(false);
  } catch (err) {
    setErr
or(err);
  }
}, [query, page])

so it will be simplified only useEffect, I don't see the point of useCallback here.

about 4 years ago · Juan Pablo Isaza Relatório

0

useCallback memoizes the function definition, so that each time a component re-renders it won't create a new definition for that function unless the dependency array fed to useCallback changes.

Here, the function with useCallback is included in a dependency array for the useEffect. Without a memoization, each time this hook is called, it will create a new function definition for searchQuery and will render again, resulting in an infinite loop.

To visualize this I have created a codesandbox example, open up console and see that the component that doesn't use the useCallback renders infinitely.

The Code:

-- Query.jsx

import useFetchWithCallback from "./useFetch";
import useFetchWithoutCallback from "./useFetchWithoutCallback";

const url = "https://jsonplaceholder.typicode.com/todos/1";

export const QueryWithCallback = () => {
  const { data } = useFetchWithCallback({
    url
  });
  console.log("Query with callback rerender");

  return <h1>Query with callback: {data?.[0]?.id}</h1>;
};

export const QueryWithoutCallback = () => {
  const { data } = useFetchWithoutCallback({
    url
  });
  console.log("Query without callback rerender");

  return <h1>Query without callback: {data?.[0]?.id}</h1>;
};

-- useFetch.js

import { useState, useEffect, useCallback } from "react";
import axios from "axios";

function useFetch({ query, page, url }) {
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(false);
  const [list, setList] = useState([]);

  const sendQuery = useCallback(async () => {
    try {
      setLoading(true);
      setError(false);
      const res = await axios.get(url);
      setList(res.data);
      setLoading(false);
    } catch (err) {
      setError(err);
    }
  }, [url]);

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

  return { loading, error, data: list };
}

export default useFetch;

--useFetchWithoutCallback.js

import { useState, useEffect, useCallback } from "react";
import axios from "axios";

function useFetch({ query, page, url }) {
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(false);
  const [list, setList] = useState([]);

  const sendQuery = async() => {
    try {
      setLoading(true);
      setError(false);
      const res = await axios.get(url);
      setList(res.data);
      setLoading(false);
    } catch (err) {
      setError(err);
    }
  }

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

  return { loading, error, data: list };
}

export default useFetch;

Note: There are other use cases for useCallback. Specifically, not re-rendering child component when it is used with React.memo(...)

about 4 years ago · Juan Pablo Isaza Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda