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

React实现无限滚动时useEffect出现依赖相关报错如何解决

问题根因

  • 第一个报错是react-hooks/exhaustive-deps语法规则检测到useEffect中用到了props.category和updateNews但未加入依赖数组,属于规范类告警。
  • 第二个报错是因为updateNews是组件内部定义的普通函数,每次组件重新渲染都会生成新的函数引用,放到useEffect依赖中会导致useEffect被无意义重复触发,存在死循环风险。

修复方案(推荐直接使用方案二,逻辑更简洁无额外钩子依赖)

方案1:用useCallback缓存updateNews函数

  1. 从react包中导入useCallback钩子
  2. 用useCallback包裹updateNews的定义,同时将状态更新改为函数式写法,避免依赖组件内部state,减少不必要的依赖项
  3. 将缓存后的updateNews加入useEffect的依赖数组即可

方案2:直接将updateNews逻辑移到useEffect内部

把updateNews的实现直接写到useEffect回调里,无需额外处理函数引用变化问题,同时修正状态更新的闭包风险,修改后完整代码如下:

import React, { useEffect, useState } from "react";
import NewsItem from "./NewsItem";
import Spinner from "./Spinner";
import PropTypes from "prop-types";
import InfiniteScroll from "react-infinite-scroll-component";

const News = (props) => {
  const [articles, setArticles] = useState([]);
  const [loading, setLoading] = useState(true);
  const [page, setPage] = useState(1);
  const [totalResults, setTotalResults] = useState(0);

  const capitalizeFirstLetter = (string) => {
    return string.charAt(0).toUpperCase() + string.slice(1);
  };

  useEffect(() => {
    // 把updateNews逻辑直接移到useEffect内部,避免函数引用变化问题
    const updateNews = async () => {
      props.setProgress(10);
      const url = `https://newsapi.org/v2/top-headlines?country=${props.country}&category=${props.category}&apiKey=${props.apiKey}&page=${page}&pageSize=${props.pageSize}`;
      props.setProgress(30);
      let data = await fetch(url);
      props.setProgress(50);
      let parsedData = await data.json();
      props.setProgress(70);
      if (parsedData) {
        // 用函数式更新,不需要依赖外部的articles变量,避免闭包问题
        setArticles(prevArticles => prevArticles.concat(parsedData.articles));
        setLoading(false);
        setTotalResults(parsedData.totalResults);
      }
      props.setProgress(100);
    };

    updateNews();
    document.title = `${capitalizeFirstLetter(props.category)} - NewsMonkey`;
    // 补全所有用到的依赖,不会出现遗漏告警也不会重复触发
  }, [page, props.category, props.country, props.apiKey, props.pageSize, props.setProgress]);

  // 改成函数式更新,避免闭包导致页码更新错误
  const fetchMoreData = () => {
    setPage(prevPage => prevPage + 1);
  };

  return (
    <>
      <h3 className="text-center" style={{ marginTop: "4%" }}>
        NewsMonkey - Top {`${capitalizeFirstLetter(props.category)}`} Headlines
      </h3>
      {loading && <Spinner />}
      <InfiniteScroll
        dataLength={articles.length}
        next={fetchMoreData}
        hasMore={articles.length < totalResults}
        loader={<Spinner />}
      >
        <div className="container">
          <div className="row">
            {articles.map((element) => {
              return (
                <div className="col-md-4" key={element.url}>
                  <NewsItem
                    title={
                      element && element.title ? element.title.slice(0, 45) : ""
                    }
                    description={
                      element && element.description
                        ? element.description.slice(0, 50)
                        : ""
                    }
                    imageUrl={element.urlToImage}
                    newsUrl={element.url}
                    author={element.author}
                    date={element.publishedAt}
                    source={element.source.name}
                  />
                </div>
              );
            })}
          </div>
        </div>
      </InfiniteScroll>
    </>
  );
};

export default News;

内容的提问来源于stack exchange,提问作者Himanshu Poddar

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 16:54:01