React useRef报Cannot set properties of null错误解决方案
问题根因
这个报错是运行时真实触发的空值访问,和TS类型校验无关。代码里的!非空断言仅能骗过TS类型检查,不会做任何运行时的空值兜底。
出现「视频能正常展示但控制台抛错」的核心原因是React 18及以上版本开发环境默认开启的严格模式(Strict Mode)机制:
- 严格模式下组件首次加载时会完整执行一次挂载流程,紧接着触发卸载、再重新挂载一次,用来提前暴露代码里的副作用、清理逻辑问题
- 第一次执行
useEffect中的getDeviceMedia方法时,navigator.mediaDevices.getUserMedia是异步操作,等权限申请通过、拿到媒体流的时候,组件已经被严格模式触发的卸载流程销毁,此时videoRef.current会被React重置为null,对null赋值srcObject就会抛出你看到的TypeError - 等组件第二次重新挂载完成后,
getDeviceMedia再次执行拿到流,此时ref已经正常绑定到DOM上的video元素,赋值成功,所以视频功能可以正常运行
除此之外当前实现还有两个必现的隐藏问题:
- 没有做ref空值兜底,生产环境如果遇到组件提前卸载、video元素被条件渲染隐藏的场景,同样会触发这个空值报错
- 没有在组件卸载时关闭媒体流,会导致摄像头一直被页面占用,用户设备摄像头指示灯常亮,造成资源泄漏
修复方案
不要用非空断言跳过校验,按以下逻辑修改即可完全解决问题:
- 所有访问
videoRef.current的位置先做非空判断,从根源避免空值赋值 - 增加卸载标记,组件卸载后不再执行后续的状态更新、ref赋值操作
- 增加副作用清理函数,组件卸载时主动关闭所有媒体轨道,释放摄像头资源
- (可选)把媒体流赋值给video元素的逻辑拆成独立的副作用,依赖
mediaStream状态,保证赋值时DOM和流都已就绪
完整修复后的代码:
const Page: React.FC = () => { const videoRef = useRef<HTMLVideoElement | null>(null) const [mediaStream, setMediaStream] = useState<MediaStream | null>(null) useEffect(() => { let isUnmounted = false const getDeviceMedia = async () => { try { const stream = await navigator.mediaDevices.getUserMedia({ video: true }) // 组件已卸载时直接释放流,不做后续操作 if (isUnmounted) { stream.getTracks().forEach(track => track.stop()) return } setMediaStream(stream) } catch (err) { // 可在此处补充用户拒绝摄像头权限的兜底提示 console.error('摄像头权限获取失败', err) } } getDeviceMedia() // 组件卸载时执行清理 return () => { isUnmounted = true if (mediaStream) { mediaStream.getTracks().forEach(track => track.stop()) } } }, []) // 监听媒体流变化,流就绪且ref存在时再赋值 useEffect(() => { if (videoRef.current && mediaStream) { videoRef.current.srcObject = mediaStream } }, [mediaStream]) return <video ref={videoRef} autoPlay muted /> }
补充说明
- 如果不想拆分两个useEffect,也可以在原赋值逻辑前加一层空值判断:
if (videoRef.current) videoRef.current.srcObject = stream,同样可以解决报错,只是拆分副作用的写法时序更稳定,不会因为异步操作的先后顺序踩坑 - 不需要为了规避这个报错关闭React严格模式,严格模式的重复挂载逻辑本质是帮你提前发现代码里缺失清理逻辑、时序不对的问题,这些问题在生产环境遇到路由切换、条件渲染时一样会出现
- 生产环境构建后会默认关闭严格模式的重复挂载行为,但空值兜底、媒体流清理的逻辑必须保留,否则会引发线上报错和设备资源泄漏
内容的提问来源于stack exchange,提问作者G. Hruschka
相关产品推荐
相关产品推荐

