Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

238
Vistas
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 Respuestas
Responde la pregunta

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 Denunciar

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 Denunciar

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 Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda