You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 21:50:37