【问题标题】:Memory leak message when i'm using history.push inside useEffect当我在 useEffect 中使用 history.push 时出现内存泄漏消息
【发布时间】:2022-09-27 23:52:21
【问题描述】:

当我在 UseEffect 函数中传递 history.push 时。

function Home(props) {
  useEffect(() => {
    const fetchData = async () => {
      const response = await listingService.allListingDetails(data.listingId);

      let tasksReceived = response.data.tasks;
      let tasks = [...tasksReceived];
      setTasks(tasks);
      setListing(response.data);

      if (tasks.length < 1) {
        history.push({
          pathname: \"/firstpage\",
          state: {
            listing: response.data,
          },
        });

        return;
      }
    };
  }, [changeState]);
}

index.js:1 警告:无法对未安装的组件执行 React 状态更新。这是一个空操作,但它表明您的应用程序中存在内存泄漏。要解决此问题,请在 useEffect 清理函数中取消所有订阅和异步任务。 在家里(http://localhost:3001/static/js/main.chunk.js:11116:79)

如果我正在评论以下行,则内存泄漏错误不会再出现。

      if (tasks.length < 1) {
        history.push({
          pathname: \"/firstpage\",
          state: {
            listing: response.data,
          },
        });

    标签: reactjs


    【解决方案1】:

    我的猜测是,react 正在尝试在重定向发生并且组件已经卸载之后应用 setTaskssetListing 的状态更新,请记住状态更新不是立即的,而是批处理的。仅当您有任务时才尝试通过设置状态来重新排序逻辑,因为在重定向时更新状态是没有意义的。

        const fetchData = async () => {
          const response = await listingService.allListingDetails(data.listingId);
          let tasksReceived = response.data.tasks;
          let tasks = [...tasksReceived];
          if (tasks.length < 1) {
            history.push({
              pathname: "/firstpage",
              state: {
                listing: response.data,
              },
            });
          } else {
            setTasks(tasks);
            setListing(response.data);
          }
        };
    

    【讨论】:

      【解决方案2】:

      这可能是因为 react 在您尝试导航的同一时刻执行状态更新(history.push)。尝试分离代码(一侧的获取,另一侧的状态更新......)并返回 history.push (清理功能)。

      function Home(props) {
      
        useEffect(() => {
            const fetchData = async () => {
              try {
                const response = await listingService.allListingDetails(data.listingId);
                let tasksReceived = response.data
                return tasksReceived;
              } catch (e) {
                  console.error(e)
                return null;
              }
            }
      
            const data = fetchData().then((data) => data);
            setTasks(data?.tasks || []);
            setListing(data || {});
            
      
            if (data?.tasks.length < 1) {
              return () => history.push({
                pathname: "/firstpage",
                state: {
                  listing: response.data,
                },
              });
            }
        }, [changeState]);
      }
      

      【讨论】:

      • 你不能将异步函数传递给useEffect
      【解决方案3】:

      这是卸载组件后更新状态时的常见错误。

      这可能是由于并发或由于调用了不必要的使用效果,具体取决于[改变状态]参数

      为了可追溯性,可以调试把下面的console.logs()

      
      const renderCount = 0;
      const useEffectCallCount = 0;
      
      function Home(props) {
        console.log(`Redering ${renderCount++}`);
      
        useEffect(() => {
          const fetchData = async () => {
            useEffectCallCount++;
            const callId = useEffectCallCount;
            console.log(`useEfect initiated. CallID: ${callId}`);
            const response = await listingService.allListingDetails(data.listingId);
      
            let tasksReceived = response.data.tasks;
            let tasks = [...tasksReceived];
            console.log(`updating component state. CallID:  ${callId}`);
            setTasks(tasks);
            setListing(response.data);
      
            if (tasks.length < 1) {
              console.log(`Redirecting to first page. CallID:  ${callId}`);
              history.push({
                pathname: "/firstpage",
                state: {
                  listing: response.data,
                },
              });
            }
          };
      
        ///probably missing from the example is calling the fetchDataItself. Fire and forget
        fetchData();
      
       /// we return clean-up function, but in this case, we want just to perform console.log
        return () => { console.log("Component is dismounted"); }
        }, [changeState]);
      }
      

      【讨论】:

        猜你喜欢
        • 2011-04-24
        • 1970-01-01
        • 2013-11-09
        • 2013-11-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-07-13
        • 1970-01-01
        相关资源
        最近更新 更多