React State返回Undefined问题:mediaRecorder在useEffect中未取到更新值
问题原因与解决方案
问题核心
你的代码存在两个关键问题:
- 闭包陷阱:
socket.on("serveVideo")的回调函数在组件某次渲染时创建,会捕获当时的mediaRecorder状态值。哪怕后续setMediaRecorder更新了状态,旧回调里依然保留着初始的空值引用。 - 清理函数不匹配:useEffect的清理逻辑移除的是
vidBlob事件监听,但你绑定的是serveVideo事件,导致旧回调一直留在socket上,触发时还是用旧的state。
修复方案一:修正清理逻辑 + 依赖state更新回调
调整useEffect的清理函数,确保每次移除对应的serveVideo事件,这样每次mediaRecorder更新时,旧回调会被清理,新回调绑定最新状态值:
const [mediaRecorder, setMediaRecorder] = useState(); const func = () => { setMediaRecorder(newVal); } useEffect(() => { const handleServeVideo = () => { mediaRecorder?.stop(); // 用可选链避免空值报错 }; socket.on("serveVideo", handleServeVideo); // 清理时移除对应事件监听 return () => { socket.off("serveVideo", handleServeVideo); }; }, [mediaRecorder]);
修复方案二:用useRef保存最新引用
如果不想每次state更新都解绑/绑定事件,可以用useRef存储mediaRecorder的最新引用,这样回调里总能拿到当前最新值:
const [mediaRecorder, setMediaRecorder] = useState(); const mediaRecorderRef = useRef(); // 每次state更新时同步ref的值 useEffect(() => { mediaRecorderRef.current = mediaRecorder; }, [mediaRecorder]); const func = () => { setMediaRecorder(newVal); } useEffect(() => { const handleServeVideo = () => { mediaRecorderRef.current?.stop(); // 从ref获取最新值 }; socket.on("serveVideo", handleServeVideo); return () => { socket.off("serveVideo", handleServeVideo); }; }, []); // 依赖为空,仅绑定一次事件
额外提示
- 调用
stop()前用可选链?.,避免mediaRecorder为空时抛出错误。 - 确认socket的
off方法需要传入对应回调才能精准移除监听,部分socket库只传事件名会移除该事件下所有监听,可根据库文档调整。
内容的提问来源于stack exchange,提问作者Ajit Kumar
相关产品推荐
相关产品推荐

