React useEffect() 无限重新渲染以获取所有尽管有依赖关系
Posted
技术标签:
【中文标题】React useEffect() 无限重新渲染以获取所有尽管有依赖关系【英文标题】:React useEffect() infinite re-render for getting all despite dependencies 【发布时间】:2022-01-12 11:01:43 【问题描述】:我对 React 比较陌生,但我一直在使用 useEffect 在页面加载时从数据库中获取我的所有新闻和事件。我最近尝试实现一个加载微调器,现在我似乎遇到了一个无限循环,但我不明白为什么。我在依赖数组中有新闻和事件,因为如果它们发生变化,那么我们需要更新显示给用户的内容。我能看到的唯一潜在问题是,我正在状态存储中的操作中构建新闻和事件数组,但在尝试实现此功能之前,我似乎没有遇到此问题。这可能是一些愚蠢的事情,但是有人可以帮助我吗?
前端代码:
export default observer(function NewsAndEvents()
const generalStore = useStore();
const getNewsAndEvents, events, news, loading = generalStore
useEffect(() =>
getNewsAndEvents();
, [news, events]);
return (
<main id="newsAndEvents">
<div className="infoContainer">
<h1>News</h1>
loading ? <LoadingSpinner /> : news.map((news, index) =>
return <News key=`news_$index` title=news.title content=news.content />
)
</div>
采取行动:
export default class GeneralStore
isAuthenticated: boolean = false;
selectedEvent: Event | undefined = undefined;
events: Event[] = [];
selectedNews: News | undefined = undefined;
news: News[] = [];
loading: boolean = false;
constructor()
makeAutoObservable(this);
getNewsAndEvents = async () =>
this.loading = true;
try
let response: any = await agent.newsAndEvents.list();
if (response !== null)
runInAction(() =>
this.events = [];
this.news = [];
response.events.forEach((item: any) =>
let newEvent: Event =
id: item._id,
date_time: item.date_time,
name: item.name,
description: item.description,
price: item.price,
type: ContentType.event,
;
this.events.push(newEvent);
);
response.news.forEach((item: any) =>
let newNews: News =
id: item._id,
title: item.title,
content: item.content,
type: ContentType.news,
;
this.news.push(newNews);
);
this.setLoading(false);
);
catch (ex)
console.log(ex);
this.setLoading(false);
;
我正在使用 TS 和 MobX。
【问题讨论】:
当news
发生变化时,为什么要更新news
?那有什么用例?
【参考方案1】:
如果您的 getNewsAndEvents()
函数正在更新 news
或 events
,您的 useEffect 将无限运行。您需要创建一个标志来防止这种情况发生。
const [flag, setFlag] = useState(true);
useEffect(() =>
if (flag)
getNewsAndEvents();
setFlag(false);
, [flag]);
理想情况下,flag 也应该是一个全局状态,但我在这里使用了 useState,因为我不熟悉 mobx。
然后每次你想让getNewsAndEvents()
运行时,你可以将标志设置为true。
【讨论】:
【参考方案2】:我认为问题是加载结束时,它的值(true)保持不变,因为加载不是组件状态,所以如果加载结束,组件不会重新渲染,所以要解决这个问题,我建议你把使用 useState 钩子的状态中的加载值:
const [loading, setLoading] = useState(generalStore.loading);
然后您将添加一个带有 [generalStore.loading] 依赖项的 useEffect,以便在加载值更改后更新状态,这将使组件重新渲染:
useEffect(() =>
setLoading(generalStore.loading);
, [generalStore.loading]);
我不确定此解决方案是否适合您,但我认为值得一试。
【讨论】:
以上是关于React useEffect() 无限重新渲染以获取所有尽管有依赖关系的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 react-hooks (useEffect) 缓冲流数据以便能够一次更新另一个组件以避免多次重新渲染?
React 限制渲染次数以防止无限循环...重新渲染次数过多
为啥错误:重新渲染太多。 React 限制了渲染的数量以防止无限循环。?
太多的重新渲染。 React 限制了渲染的数量以防止无限循环。?