首页 > 解决方案 > 当 useEffect 道具改变时反应停止超时

问题描述

我正在构建和 React 应用程序,我必须在其中保存用户当前在线显示文档的哪个页面,但是有一个问题,如果用户滚动整个文档,它会保存所有页面。所以我们想使用某种计时器功能,例如,只有在道具页面在 30 秒内没有变化时才会触发。这是我的代码,它稍后会调用,但仍然适用于滚动中的所有页面。

useEffect(
        async () => {
            let timeout;
            if (scriptInfo && authData && numPages) {
                setTimeout(async () => {
                    const res = await postScriptAnalyticsData({
                        script_id: scriptInfo._id,
                        user_id: authData.user.user_id,
                        page: page,
                        full_page: numPages
                    });
                }, 10000);
            }

            return () => {
                clearTimeout(timeout);
            };
        },
        [ scriptInfo, page, authData, numPages ]
    );

标签: javascriptreactjstimeout

解决方案


你的useEffect()回调函数不应该是async. 当返回值时,useEffect 钩子应该返回一个函数,但如果你的回调是async,那么它将隐式返回一个 Promise。async从您的 useEffect 回调中删除,因为您没有直接在函数中使用,所以不需要这样做await。此外,将 分配给timeoutsetTimeout() 的返回值,以便您可以清除它:

useEffect(() => { // can't be `async`, so remove it
    let timeout;
    if (scriptInfo && authData && numPages) {
      timeout = setTimeout(async () => { // assign `timeout`
        const res = await postScriptAnalyticsData({
          script_id: scriptInfo._id,
          user_id: authData.user.user_id,
          page: page,
          full_page: numPages
        });
      }, 10000);
    }

    return () => {
      clearTimeout(timeout);
    };
  }, 
  [scriptInfo, page, authData, numPages]
);

推荐阅读