Reputation: 109
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
Upvotes: 0
Views: 99
Reputation: 349
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);
}, [])
Or another way, you can put getMoviesData func
outside useEffect
, but you need add useCallback
for getMoviesData
like this:
const getMoviesData = useCallback(async (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))
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [])
useEffect(() => {
getMoviesData(url, tvUrl, topPicks, kidsMovieURL, kidsTvURL, kidsSeries);
}, [getMoviesData])
Upvotes: 0
Reputation: 1677
When using useEffect
, one thing to keep in mind is that any state variable or function that is defined inside the component and 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:
getMoviesData
inside the useEffect
's effect
function (if you are not using it outside the useEffect
hook)useCallback
to memoize the function reference (if you are using the function outside the useEffect
)In your case, you need 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);
}, [setMovies, setTopMovies, setKidsMovies, setKidsTv, setKidsTvSeries])
Upvotes: 1
Reputation: 1108
You just have to memorize the function using useCallback
and 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])
Upvotes: 1
Reputation: 24
Mayve you could try something like that (using useCallback):
const getMoviesData = useCallback(() => { /* your code */ }, []);
Upvotes: -1