My App's "React Hook useEffect has a missing dependency" warning

Viewed 99

I have a simple app for searching a db of Albums by artist.
Three components: App, AlbumList, AlbumSearch.

The App component defines getAlbumsByArtist to fetch and update albums, and passes albums as prop to AlbumList.

App defines getAlbumsByArtist to pass as prop to AlbumSearch. In AlbumSearch, when the artist is changed, I useEffect to call getAlbumsByArtist.

The app works, but in AlbumSearch I get a warning of React Hook useEffect has a missing dependency: 'getAlbumsByArtist'.

How can I refactor to fix this warning?

import React, { useState, useEffect } from "react";

function App() {
  const [albums, setAlbums] = useState(false);

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

  function getAlbums() {
    fetch("http://localhost:3001")
      .then((response) => response.json())
      .then((data) => setAlbums(data));
  }

  function getAlbumsByArtist(artist) {
    fetch(`"http://localhost:3001"/albums?artist=${artist}`)
      .then((response) => response.json())
      .then((data) => setAlbums(data));
  }

  return (
    <div>
      <h2>Albums</h2>
      <AlbumSearch getAlbumsByArtist={getAlbumsByArtist} />
      <AlbumList albums={albums} />
    </div>
  );
}

function AlbumSearch({ getAlbumsByArtist }) {
  const [artist, setArtist] = useState("");

  useEffect(() => {
    getAlbumsByArtist(artist);
  }, [artist]);

  const handleArtist = (e) => {
    e.preventDefault();
    setArtist(e.target.value);
  };

  return (
    <div className={`album-search ${showSearchClass}`}>
      <div>
        <label>Artist contains: </label>
        <input
          id="searchArtist"
          type="text"
          value={artist}
          onChange={handleArtist}
        />
      </div>
    </div>
  );
}

function AlbumList({ albums }) {
  return (
    <div>
      <header>
        <div>Id</div> <div>Artist</div> <div>Title</div>{" "}
      </header>
      <div>
        {albums &&
          albums.map((album) => {
            return (
              <div key={album.id}>
                <div>{album.id}</div>
                <div>{album.artist}</div>
                <div>{album.title}</div>
              </div>
            );
          })}
      </div>
    </div>
  );
}
1 Answers

As react will guarantee that a setState() function will never change, you can simply add the getAlbumsByArtist function to your useEffect() dependencies to get the same result.

useEffect(() => {
    getAlbumsByArtist(artist);
  }, [getAlbumsByArtist, artist]);

Another way would be to simply irgnore the warning by:

useEffect(() => {
   getAlbumsByArtist(artist);
}, [getAlbumsByArtist, artist]); // eslint-disable-line react-hooks/exhaustive-deps
Related