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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 07:10:29