React项目中useEffect触发截图偶尔为null且函数多次执行问题求助
React自动截图功能问题修复方案
问题根源
- 截图结果偶尔为null
takeScreenShot为异步方法,React的状态更新不是同步生效,调用后立刻读取screenshot状态会拿到更新前的初始值null- 函数组件错误使用
createRef,该API每次渲染都会生成新的ref实例,容易导致DOM绑定失效 - 组件挂载初期可能存在DOM未渲染完成的情况,
ref.current为空时传入截图方法也会返回null
- 函数多次执行
- React18开发环境默认开启严格模式,空依赖的useEffect会被执行两次,属于框架正常设计,用于校验副作用逻辑的健壮性
- 未处理异步逻辑导致的状态更新触发的重复渲染,也会引发逻辑重复执行
修复后完整代码
import { useRef, useEffect } from 'react'; import jwtDecode from 'jwt-decode'; import axios from 'axios'; // 保留原有useScreenshot、AuthService的导入逻辑 function Products() { // 替换createRef为useRef,保证组件生命周期内ref唯一 const ref = useRef(null); const [screenShoot, takeScreenShot] = useScreenshot(); // 新增标识位避免严格模式下重复触发截图 const executedRef = useRef(false); const getImage = () => { // 增加DOM存在性判断,避免传空值 if (ref.current) { takeScreenShot(ref.current); } }; // 监听截图状态,只有拿到有效截图后再发起接口请求 useEffect(() => { if (!screenShoot || !executedRef.current) return; const data = { id: jwtDecode(AuthService.getCurrentUser().accessToken).id, screenShoot }; axios.post("http://localhost:8080/api/auth/screenshoot", data) .then((response) => { console.log(response.data); }) .finally(() => { executedRef.current = false; }); }, [screenShoot]); useEffect(() => { if (executedRef.current) return; executedRef.current = true; getImage(); }, []); return ( <div ref={ref}> Welcome user </div> ) }
关键修改说明
- 替换
createRef为useRef,适配函数组件的ref使用规范 - 新增
screenshot状态监听逻辑,等异步截图生成完成后再发起接口请求,避免读取空值 - 新增ref标识位,屏蔽开发环境严格模式下的重复执行问题,该问题生产环境会自动消失
- 增加DOM存在性校验,避免DOM未渲染完成时调用截图方法报错
内容的提问来源于stack exchange,提问作者Jhonny
相关产品推荐
相关产品推荐

