You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在useIdleTimer的onIdle回调中获取最新user状态?

解决useIdleTimer回调中无法获取最新user状态的问题

你遇到的是典型的闭包陷阱:useIdleTimer初始化时,handleOnIdle捕获的是组件首次渲染时的user值(也就是null),后续user更新时,这个回调函数的引用没有更新,定时器依然调用旧的回调,所以始终拿不到最新的user。

下面给你两种可行的解决方案:

方案一:用useRef保存最新user引用

通过useRef存储user的最新值,因为ref的.current属性是可变的,不受闭包限制,回调里直接取userRef.current就能拿到最新状态:

const { user } = useTypedSelector((state) => state.auth)
const userRef = useRef(user);

// 同步user状态到ref
useEffect(() => {
  userRef.current = user;
}, [user]);

const [isInactiveModalActive, setIsInactiveModalActive] = useState(false)

const handleOnIdle = () => {
    if (userRef.current) {
        setIsInactiveModalActive(true)
    }
}

useIdleTimer({
    onIdle: handleOnIdle,
    timeout: 1000,
    crossTab: true,
    debounce: 500,
})

方案二:让定时器随user变化重新初始化

用useCallback包裹handleOnIdle,把user作为依赖项,同时给useIdleTimer添加依赖,确保user更新时,定时器会重新初始化并绑定新的回调:

const { user } = useTypedSelector((state) => state.auth)

const [isInactiveModalActive, setIsInactiveModalActive] = useState(false)

// 每次user变化时生成新的回调
const handleOnIdle = useCallback(() => {
    user && setIsInactiveModalActive(true)
}, [user]);

// 依赖handleOnIdle,回调更新时重新创建定时器
useIdleTimer({
    onIdle: handleOnIdle,
    timeout: 1000,
    crossTab: true,
    debounce: 500,
}, [handleOnIdle]);

两种方案对比

  • 方案一不会频繁重新创建定时器,性能更优,适合大部分场景;
  • 方案二每次user变化都会重启定时器,如果你需要在用户登录/登出时重置闲置计时,可以选这种。

内容的提问来源于stack exchange,提问作者nikulas13

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 09:42:38