I was trying to add the async function in useEffect. While doing this I am getting the warning about wrap fetchData function in useCallback hook. So, Where should I declare the useCallback function, and how to implement it?

Here is the code:

    import React, { useState, useEffect, useCallback } from 'react'
    import './assets/main.css'
    import ImageCard from './components/ImageCard'
    import ImageSearch from './components/ImageSearch'
    function App() {
      const [images, setImages] = useState([])
      const [isLoading, setIsLoading] = useState(true)
      const [serachTerm, setSearchTerm] = useState('')
    
      const fetchData = async () => {
        try {
          const data = await fetch(
            `https://pixabay.com/api/?key=${process.env.REACT_APP_PIXABAY_API_KEY}&q=${serachTerm}&image_type=photo&pretty=true`
          ).then(res => res.json())
          setImages(data.hits)
          setIsLoading(false)
        } catch (err) {
          console.log(err)
        }
      }
    
    
      useEffect(() => {
        fetchData()
        setIsLoading(false)
      }, [setSearchTerm, fetchData])

1

There are 1 answers

0
Drew Reese On

The warning is about fetchData being redeclared each render cycle, thus retriggering the useEffect callback. The useCallback memoizes the function to provide a stable reference.

You have two options:

Memoize fetchData with useCallback

const fetchData = useCallback(async () => {
  try {
    const data = await fetch(
      `https://pixabay.com/api/?key=${process.env.REACT_APP_PIXABAY_API_KEY}&q=${serachTerm}&image_type=photo&pretty=true`
    ).then((res) => res.json());
    setImages(data.hits);
  } catch (err) {
    console.log(err);
  } finally {
    setIsLoading(false); // <-- set loading false when done no matter what
  }
}, [serachTerm]); // <-- add any missing dependencies react warns about

useEffect(() => {
  fetchData();
  setIsLoading(true); // <-- I think you meant for loading true
}, [setSearchTerm, fetchData]); // <-- double check setSearchTerm dependency

Move fetchData into the useEffect hook so its reference doesn't matter

useEffect(() => {
  const fetchData = async () => {
    try {
      const data = await fetch(
        `https://pixabay.com/api/?key=${process.env.REACT_APP_PIXABAY_API_KEY}&q=${serachTerm}&image_type=photo&pretty=true`
      ).then((res) => res.json());
      setImages(data.hits);
    } catch (err) {
      console.log(err);
    } finally {
      setIsLoading(false);
    }
  };

  fetchData();
  setIsLoading(true);
}, [setSearchTerm]);