ReactJS -> 未捕获错误:重新渲染太多。React 限制渲染数量以防止无限循环



我是React的新手,我在网上跟随教程。在教程中,我们已经使用基于类的组件制作了一个应用程序,而不是将其更改为基于函数的组件。当我的应用程序使用基于类的组件时,它正在工作,但是当我切换它并尝试使用钩子时,我得到了这个错误。

可能导致错误的代码:

import NewsItem from './NewsItem'
import PropTypes from 'prop-types'
import Spinner from './Spinner';
import InfiniteScroll from "react-infinite-scroll-component";
function NewsView(props) {
const [articles, setArticles] = useState([])
const [page, setPage] = useState(1)
const [totalResults, setTotalResults] = useState(10)
const update =  async () => {
props.handleProgress(0)
let url = `https://newsapi.org/v2/top-headlines?&category=${props.category}&country=${props.country}&apiKey=${props.key}&pageSize=${props.pageSize}&page=${page}`
const response = await fetch(url);
props.handleProgress(30)
let data = await response.json();
props.handleProgress(70)
props.handleProgress(100)
setArticles(articles.concat(data.articles))
setTotalResults(data.totalResults)
}
const fetchMoreData = () => {
setPage(page + 1)
update()
}
useEffect(() => {
update()

}, [])
return (
<div className='container my-2 '>
<div className={`container text-center my-4 text-${props.darkmode ? "light" : "dark"}`}>
<h1>Top {props.category[0].toUpperCase()}{props.category.slice(1)} Headlines</h1>
</div>
<InfiniteScroll
dataLength={articles.length}
next={fetchMoreData}
hasMore={articles.length < totalResults}
loader={<Spinner />}
>
<div className="row d-flex justify-content-center" >
{articles.map((article, index) => {
if (article.urlToImage != null) {
return (
<div className="col" key={index}>
<NewsItem darkmode={props.darkmode} title={article.title} description={article.description} url={article.url} urlToImage={article.urlToImage} author={article.author} time={article.publishedAt} source={article.source.name} ></NewsItem>
</div>)
}
return null;
})}
</div>
</InfiniteScroll>
</div>
)
}
NewsView.propTypes = {
category: PropTypes.string.isRequired,
country: PropTypes.string.isRequired,
pageSize: PropTypes.number.isRequired,
darkmode: PropTypes.bool.isRequired,
handleProgress: PropTypes.func.isRequired,
}
//set default props
NewsView.defaultProps = {
darkmode: false,
}
export default NewsView

我已经尝试添加useCallback来更新函数,并添加一个条件,使其运行,如果它是真的,然后把它变成假,即只是使它在一次运行后为假。

我不知道出了什么问题这是我在终端中得到的:
[eslint] 
src/components/NewsView.js
Line 35:8:  React Hook useEffect has a missing dependency: 'update'. Either include it or remove the dependency array  react-hooks/exhaustive-deps
Search for the keywords to learn more about each warning.
To ignore, add // eslint-disable-next-line to the line before.
WARNING in [eslint] 
src/components/NewsView.js
Line 35:8:  React Hook useEffect has a missing dependency: 'update'. Either include it or remove the dependency array  react-hooks/exhaustive-deps
webpack compiled with 1 warning

这里是控制台中的错误

Uncaught Error: Too many re-renders. React limits the number of renders to prevent an infinite loop.
at renderWithHooks (react-dom.development.js:16317:1)
at mountIndeterminateComponent (react-dom.development.js:20074:1)
at beginWork (react-dom.development.js:21587:1)
at HTMLUnknownElement.callCallback (react-dom.development.js:4164:1)
at Object.invokeGuardedCallbackDev (react-dom.development.js:4213:1)
at invokeGuardedCallback (react-dom.development.js:4277:1)
at beginWork$1 (react-dom.development.js:27451:1)
at performUnitOfWork (react-dom.development.js:26557:1)
at workLoopSync (react-dom.development.js:26466:1)
at renderRootSync (react-dom.development.js:26434:1)

这通常是由于useEffect的状态作为依赖项被更新。例如,如果您在useEffect中调用setArticles,并将articles作为依赖项,则它将永远循环。

你仍然可以使用useEffect来更新文章。如果你比较新旧文章,只有当它们不同时才调用setArticles。可以这样做

useEffect(() => {
if (newArticles !== oldArticles) {
setArticles(newArticles)
}
}, [newArticles])

小心这里的检查,JS不喜欢比较对象,所以你可能需要写一个函数来检查数组中的每个对象。我不确定。

还要确保在呈现状态时实现空检查。这将防止页面在抓取文章时出现问题而崩溃。例如:

return (
<>
{
// Simply checking if there are articles
filteredArticles
? 'There are articles' 
: 'No articles'
}
{
// Or printing individual articles
filteredArticles && filteredArticles.map((article) => <Article article={article} />)
}
{
// Null checking with Typescript
filteredArticles?.map((article) => <Article article={article} />)
}
</>
)