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() 函数正在更新 newsevents,您的 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 限制了渲染的数量以防止无限循环。?

“错误:重新渲染过多。React 限制了渲染次数以防止无限循环。”

收到此错误:错误:重新渲染过多。 React 限制渲染次数以防止无限循环