useEffect 道具更改时反应停止超时

React stop timeout when useEffect prop changes

我正在构建 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 ]
    );

声明 setTimeout() ... ,出于组件原因或者如果它没有使用挂钩 并将其保存在变量中 例如:

const timerCustom = setTimeout(...)

// 组件 使用效果(()=> { ... clearTimeout(timerCustom); ... })

当你的页面道具改变时清除它

你的 useEffect() 回调函数不应该是 async。当值被 returned 时,useEffect 钩子应该 return 一个函数,但是如果你的回调是 async,那么它将隐含地 return 一个 Promise。从您的 useEffect 回调中删除 async,因为这不是必需的,因为您没有直接在函数中使用 await。此外,将 timeout 分配给 setTimeout() 的 return 值,以便您可以清除它:

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]
);