React中visibilityChange事件传递视频观看时间参数未更新问题
问题:页面跳转时visibilityChange触发的API未传递最新状态数据
需求是在用户关闭、刷新页面或跳转到其他页面时,通过visibilityChange事件将视频观看时间等数据通过API同步到服务器。目前跳转页面时API能正常调用,但传递的played_time、MET_value等参数未更新为最新值,日志显示viewTime为空字符串、MET为undefined。
原因分析
核心问题是闭包陷阱:
- 初始渲染时,
useEffect的依赖数组为空,导致内部绑定的sendViewTime函数是组件首次渲染时创建的版本 - 这个旧函数捕获的是初始状态的
played_time和MET_value,后续状态更新后,事件监听器依然绑定的是旧函数,触发时自然拿不到最新值 - 另外,
useEffect使用async是错误的,因为useEffect的返回值必须是清理函数,async会返回Promise,导致清理逻辑失效
解决方案
1. 用useCallback包裹sendViewTime,确保捕获最新状态
通过useCallback缓存函数,只有当依赖的状态/ props变化时,才重新创建函数,保证函数始终能访问到最新值:
import { useCallback } from 'react'; const sendViewTime = useCallback(async () => { if (document.visibilityState === "hidden") { console.log("文档已隐藏"); const value = localStorage.getItem("jwt"); const initialValue = JSON.parse(value); console.log("要发送的观看时长:", played_time); const params = { video_id: video_id_url, viewTime: played_time, MET: MET_value, weight: "", }; console.log("请求参数:", params); try { const res = await setEffort(params, initialValue); console.log("API响应:", res); } catch (err) { console.error("API调用失败:", err); } } else { console.log("文档恢复可见"); } }, [played_time, MET_value, video_id_url]); // 列出所有用到的状态和props作为依赖
2. 修复useEffect的事件绑定逻辑
移除async,并将sendViewTime加入依赖数组,确保每次函数更新时重新绑定监听器:
useEffect(() => { console.log("绑定visibilityChange监听器"); window.addEventListener("visibilitychange", sendViewTime); // 清理函数:组件卸载或依赖变化时移除监听器 return () => { console.log("移除visibilityChange监听器"); window.removeEventListener("visibilitychange", sendViewTime); }; }, [sendViewTime]); // 依赖sendViewTime,函数更新时重新绑定
3. 优化onProgress的日志输出(可选)
由于setPlayed_time是异步更新状态,直接打印played_time会显示旧值,改成打印刚计算的time_2更准确:
onProgress={(time) => { console.log("当前播放时间:", time); const time_1 = Math.round(time.playedSeconds); const time_2 = JSON.stringify(time_1); setPlayed_time(time_2); console.log("更新后的观看时长:", time_2); // 直接打印最新计算值 }}
关键说明
useCallback的依赖必须完整,否则依然会出现闭包陷阱- 禁止在
useEffect中使用async,因为这会导致清理函数无法正常执行,可能引发内存泄漏 - 每次
sendViewTime更新时,useEffect会先移除旧的监听器,再绑定新的,避免重复绑定和旧函数执行
内容的提问来源于stack exchange,提问作者saad khan
相关产品推荐
相关产品推荐

