React Hook useEffect has a missing dependency.
Line 92:4: React Hook useEffect has a missing dependency: 'getMoviesData'. Either include it or remove the dependency array react-hooks/exhaustive-deps
Can someone tell me how to fix this error? I'm sure it's something very simple but any help would be greatly appreciated!
function App() {
// * MOVIE API *
//State
const [movies, setMovies] = useState([])
const [topMovies, setTopMovies] = useState([])
const [kidsMovies, setKidsMovies] = useState([])
const [setKidsTv] = useState([])
//kidsTv
const [setTvShows] = useState([])
//TvShows
const [kidsTvSeries, setKidsTvSeries] = useState([])
//API URL
const url = 'https://api.themoviedb.org/3/discover/movie?api_key=&with_genres=28/';
const tvUrl = 'https://api.themoviedb.org/3/tv/popular?api_key=8&language=en-US&page=1';
const kidsMovieURL = 'https://api.themoviedb.org/3/discover/movie?api_key=8&certification_country=US&certification.lte=G&with_genres=16&include_adult=false&sort_by=popularity.desc';
const kidsTvURL = 'https://api.themoviedb.org/3/tv/popular?api_key=8&language=en-US&page=1&with_genres=16&include_adult=false&sort_by=popularity.desc';
const topPicks = 'https://api.themoviedb.org/3/movie/top_rated?api_key=&language=en-US&page=1';
const kidsSeries = 'https://api.themoviedb.org/3/discover/tv?api_key=1f7c961ae4f02a23e0968d449c15bc98&with_genres=10762'
//Async function to fetch API
async function getMoviesData (url, tvUrl, topPicks, kidsMovieURL, kidsTvUrl, kidsSeries) {
await fetch(url).then(res => res.json()).then(data => setMovies(data.results))
await fetch(topPicks).then(res => res.json()).then(data => setTopMovies(data.results))
await fetch(tvUrl).then(res => res.json()).then(data => setTvShows(data.results))
await fetch(kidsMovieURL).then(res => res.json()).then(data => setKidsMovies(data.results))
await fetch(kidsTvUrl).then(res => res.json()).then(data => setKidsTv(data.results))
await fetch(kidsSeries).then(res => res.json()).then(data => setKidsTvSeries(data.results))
}
//Use Effect
useEffect(() => {
getMoviesData(url, tvUrl, topPicks, kidsMovieURL, kidsTvURL, kidsSeries);
}, [])
return (
<div className='app'>
<div className="header">
<Header Home={Home} Movies={Movies} Kids={Kids} Music={lazyMusic} movies={movies} topMovies={topMovies} kidsMovies={kidsMovies} kidsTvSeries={kidsTvSeries} />
</div>
<div className="music-player">
<MusicPlayer />
</div>
</div>
)
}
export default App
CodePudding user response:
Mayve you could try something like that (using useCallback):
const getMoviesData = useCallback(() => { /* your code */ }, []);
CodePudding user response:
You just have to add the getMoviesData
to the dependency array of the useEffect
.
const getMoviesData = useCallback(async () => {
await fetch(url).then(res => res.json()).then(data => setMovies(data.results))
await fetch(topPicks).then(res => res.json()).then(data => setTopMovies(data.results))
await fetch(tvUrl).then(res => res.json()).then(data => setTvShows(data.results))
await fetch(kidsMovieURL).then(res => res.json()).then(data => setKidsMovies(data.results))
await fetch(kidsTvUrl).then(res => res.json()).then(data => setKidsTv(data.results))
await fetch(kidsSeries).then(res => res.json()).then(data => setKidsTvSeries(data.results))
}, [])
useEffect(() => {
getMoviesData(url, tvUrl, topPicks, kidsMovieURL, kidsTvURL, kidsSeries);
}, [getMoviesData])
CodePudding user response:
You should move getMoviesData func
inside callback of useEffect
like this:
//Use Effect
useEffect(() => {
//Async function to fetch API
async function getMoviesData (url, tvUrl, topPicks, kidsMovieURL, kidsTvUrl, kidsSeries) {
await fetch(url).then(res => res.json()).then(data => setMovies(data.results))
await fetch(topPicks).then(res => res.json()).then(data => setTopMovies(data.results))
await fetch(tvUrl).then(res => res.json()).then(data => setTvShows(data.results))
await fetch(kidsMovieURL).then(res => res.json()).then(data => setKidsMovies(data.results))
await fetch(kidsTvUrl).then(res => res.json()).then(data => setKidsTv(data.results))
await fetch(kidsSeries).then(res => res.json()).then(data => setKidsTvSeries(data.results))
}
getMoviesData(url, tvUrl, topPicks, kidsMovieURL, kidsTvURL, kidsSeries);
}, [])
CodePudding user response:
When using useEffect
, one thing to keep in mind is that any state variable or any function that is used inside the effect
function (the 1st argument passed to useEffect
) should be included in the dependency array (the 2nd argument).
In your component, you are using the getMoviesData
function inside the useEffect
hook, but you have not included that in the dependency array. That is why you are getting the linter warning. To fix this, you just have to add the function in the dependency array. So your useEffect
hook will become this:
useEffect(() => {
getMoviesData(url, tvUrl, topPicks, kidsMovieURL, kidsTvURL, kidsSeries);
}, [getMoviesData])
However, this creates a problem - this means that whenever the getMoviesData
function is recreated, the effect will run once again. Since this function is updating the state, it will cause the component to re-render, which will then cause this function to be re-created, which in turn will cause the effect to run again, creating an infinite loop.
To solve this, you have a few options:
- Move the
getMoviesData
inside theuseEffect
'seffect
function (if you are not using it outside theuseEffect
hook) - Move it outside the component (if you are not interacting with state or any other component methods)
- Wrap it with
useCallback
to memoize the function reference.
In your case, you can go with option #1.
useEffect(() => {
function getMoviesData (url, tvUrl, topPicks, kidsMovieURL, kidsTvUrl, kidsSeries) {
fetch(url).then(res => res.json()).then(data => setMovies(data.results))
fetch(topPicks).then(res => res.json()).then(data => setTopMovies(data.results))
fetch(tvUrl).then(res => res.json()).then(data => setTvShows(data.results))
fetch(kidsMovieURL).then(res => res.json()).then(data => setKidsMovies(data.results))
fetch(kidsTvUrl).then(res => res.json()).then(data => setKidsTv(data.results))
fetch(kidsSeries).then(res => res.json()).then(data => setKidsTvSeries(data.results))
}
getMoviesData(url, tvUrl, topPicks, kidsMovieURL, kidsTvURL, kidsSeries);
}, [getMoviesData])