React Hook useEffect依赖缺失报错,如何修复?
修复React Hook useEffect缺失依赖的报错
首先纠正你代码里的两个状态定义错误:
const [setKidsTv] = useState([])应该改为const [kidsTv, setKidsTv] = useState([])const [setTvShows] = useState([])应该改为const [tvShows, setTvShows] = useState([])
这两个错误会导致你无法正确更新对应的状态数据。
接下来解决useEffect的依赖报错问题:eslint的react-hooks/exhaustive-deps规则要求useEffect回调中用到的所有外部函数/变量都必须加入依赖数组,下面是三种可行的修复方案:
方案一:用useCallback包裹getMoviesData并加入依赖数组
通过useCallback缓存函数实例,避免每次渲染重新创建函数导致useEffect重复执行:
import { useState, useEffect, useCallback } from 'react'; function App() { // 修正后的状态定义 const [movies, setMovies] = useState([]) const [topMovies, setTopMovies] = useState([]) const [kidsMovies, setKidsMovies] = useState([]) const [kidsTv, setKidsTv] = useState([]) const [tvShows, setTvShows] = useState([]) 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' // 用useCallback缓存函数 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)) }, [setMovies, setTopMovies, setTvShows, setKidsMovies, setKidsTv, setKidsTvSeries, url, tvUrl, topPicks, kidsMovieURL, kidsTvURL, kidsSeries]) useEffect(() => { getMoviesData(); }, [getMoviesData]) // 将getMoviesData加入依赖数组 // 其余代码不变 }
注:useState返回的setter函数是稳定的,不会随渲染变化;URL都是常量,同样不会变化,因此加入依赖数组不会导致额外渲染。
方案二:将getMoviesData移到useEffect内部
把函数定义直接放在useEffect回调里,无需处理外部依赖:
function App() { // 修正后的状态定义 const [movies, setMovies] = useState([]) const [topMovies, setTopMovies] = useState([]) const [kidsMovies, setKidsMovies] = useState([]) const [kidsTv, setKidsTv] = useState([]) const [tvShows, setTvShows] = useState([]) 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' useEffect(() => { // 在effect内部定义函数 async function getMoviesData() { 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(); }, []) // 依赖数组为空,仅组件挂载时执行一次 // 其余代码不变 }
这种方案适合函数仅在effect内部使用的场景,代码更简洁,无需处理依赖缓存。
方案三:临时关闭eslint警告(不推荐)
如果你确定该effect只需要执行一次,且不会因依赖变化需要重新执行,可以添加注释关闭规则警告:
useEffect(() => { getMoviesData(url, tvUrl, topPicks, kidsMovieURL, kidsTvURL, kidsSeries); }, []) // eslint-disable-line react-hooks/exhaustive-deps
注:这种方法会跳过eslint的依赖检查,可能隐藏潜在bug(比如后续依赖变化时effect不会重新执行),仅在明确知晓风险时使用。
内容的提问来源于stack exchange,提问作者Gavin-walsh
相关产品推荐
相关产品推荐

