【问题标题】:React useEffect with several HTTP calls使用多个 HTTP 调用响应 useEffect
【发布时间】:2021-05-31 11:38:10
【问题描述】:

我正在尝试使用 useEffect 和 useState 在组件中进行许多 HTTP 调用,以存储此 http 调用的结果。我以为我对 useEffect 的工作原理有了基本的了解,但我很困惑为什么我的代码不起作用,因此一定是错误地实现了它。

这是我的仪表板组件中的 useEffect 挂钩代码:

useEffect(() => {       
    isMounted.current = true;

    const fetchData = async () => {
      if (survey === null) {
        const surveyResponse = await getSurveys('standard');
        setSurvey(surveyResponse.data);
      }

      if (teamInfo === null) {
        const teamInfoResponse = await getTeamInfo(user.teamId);
        setTeamInfo(teamInfoResponse.data);
      }

      if (week === null || year === null) {
        const weekAndYearResponse = await getWeekAndYear();
        setWeek(weekAndYearResponse.data.weekNumber);
        setYear(weekAndYearResponse.data.year);
      }

      if (week && year && !stats) {
        const statsResponse = await getTeamSurveyStats(week, year, user.teamId);
        setStats(statsResponse.data);
      }
    };

    fetchData();

    return () => {
      // executed when unmount
      isMounted.current = false;
    };
  }, [survey, teamInfo, week, year, stats, user.teamId]);

我认为检查我是否为每个调用的返回设置的状态值,我可以将这个 http 调用放入一个条件中,如果该变量为空,它只会在重新渲染时发出 http 请求,正如我使用 useState(null) 定义的那样。

当我检查我的网络标签时,我看到以下内容:

第一次调用只运行一次,这是正确的 - 这是 getSurveys 第二个调用运行两次,这是不正确的,因为只需要运行一次 - 这是 getTeamInfo 第三次调用运行 5 次,这很奇怪,因为只需要运行一次 - 这是 getWeekAndYear 第四个调用只运行一次,这是正确的。

谁能明白为什么其中 2 个调用会运行多次? 谢谢

【问题讨论】:

    标签: reactjs http use-effect


    【解决方案1】:

    我将尝试引导您了解前 2 次调用中发生的情况,以便您能够推断其余部分发生的情况。

    当您的仪表板元素首次加载时,useEffect 会运行您的代码。具体来说,它运行这个函数fetchData

    fetchData 看到 survey 为空并运行此代码:

    const surveyResponse = await getSurveys('standard');
    setSurvey(surveyResponse.data);
    

    当该代码调用setSurvey(surveyResponse.data); 并更新您的状态变量时,我假设它是surveyuseEffect 再次运行。它在完成原始的安装运行之前这样做。所以现在您在管道中有 2 个fetchData 调用,其中一个已部分完成。我们称他们为 1st 和 2nd。

    第一个现在在这个街区,可能正在等待getTeamInfo 电话:

    const teamInfoResponse = await getTeamInfo(user.teamId);
    setTeamInfo(teamInfoResponse.data);
    

    同时,第二个突然进入并进入同一个代码块(因为survey 不再为空,但teamInfo 仍然是)。所以现在第一个和第二个都在运行const surveyResponse = await getSurveys('standard');

    因此两次调用getTeamInfo

    然后这个:

    setTeamInfo(teamInfoResponse.data);
    

    触发另一个 useEffect 运行,这次是因为 teamInfo 已更新。我想你明白了……

    【讨论】:

    • 嗨,是的,这完全有道理。在使用 Angular 7 年多之后,我才使用 React 9 个月,所以钩子对我来说相对较新。我认为一旦在设置第一个状态变量后调用了重新渲染,原来的 useEffect 调用就被取消了!
    【解决方案2】:

    useEffect 挂钩每次在数组中传递的某些值发生更改时被调用。 在survey 改变后会第二次调用,但此时timeInfo 没有加载,所以请求会重复,并且对于其他变量都会发生这种情况。另外,这里回答https://stackoverflow.com/a/54120692/14349629

    【讨论】:

      【解决方案3】:

      每次数组的任何变量(作为第二个参数传递)时都会调用useEffect。

      试试下面的代码

      useEffect(() => {       
          isMounted.current = true;
      
          const fetchData = async () => {
            if (survey === null) {
              const surveyResponse = await getSurveys('standard');
              setSurvey(surveyResponse.data);
              return;
            }
      
            if (teamInfo === null) {
              const teamInfoResponse = await getTeamInfo(user.teamId);
              setTeamInfo(teamInfoResponse.data);
              return;
            }
      
            let weekAndYearResponse = {};
            if (week === null || year === null) {
              weekAndYearResponse = await getWeekAndYear();
              setWeek(weekAndYearResponse.data.weekNumber);
              setYear(weekAndYearResponse.data.year);
            }
      
            if (weekAndYearResponse.data.weekNumber && weekAndYearResponse.year && !stats) {
              const statsResponse = await getTeamSurveyStats(weekAndYearResponse.data.weekNumber, weekAndYearResponse.year, user.teamId);
              setStats(statsResponse.data);
            }
          };
      
          fetchData();
      
          return () => {
            // executed when unmount
            isMounted.current = false;
          };
        }, [user.teamId]);
      

      【讨论】:

        猜你喜欢
        • 2017-03-28
        • 1970-01-01
        • 2018-12-27
        • 2019-10-01
        • 2013-09-20
        • 2021-11-26
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多