React TypeError: wrapper is null报错及定时器间隔异常求助
解决React中TypeError: wrapper is null的问题
问题原因
- DOM未挂载时获取元素:组件函数执行时,
return中的DOM还未渲染到页面,此时document.getElementById("wrapper")返回null,直接调用wrapper.dataset必然报错。 - 未清理定时器:组件卸载后
setInterval不会自动停止,会造成内存泄漏,还可能在组件卸载后继续执行引发错误。 - 全局变量
prev的副作用:prev定义在组件外部,组件多次渲染或存在多个实例时会共享该变量,导致逻辑混乱。
修复方案
使用React官方推荐的useRef获取DOM、useEffect管理定时器、useState维护组件内部状态,代码修改如下:
import React, { useRef, useEffect, useState } from 'react'; import './portfolio.css'; const rand = (min, max) => Math.floor(Math.random() * (max - min + 1) + min); const uniqueRand = (min, max, prev) => { let next = prev; while(prev === next) next = rand(min, max); return next; } const combinations = [ { configuration: 1, roundness: 1 }, { configuration: 1, roundness: 2 }, { configuration: 1, roundness: 3 }, { configuration: 2, roundness: 2 }, { configuration: 2, roundness: 3 } ]; const Portfolio = () => { // 用useRef绑定DOM元素 const wrapperRef = useRef(null); // 用useState维护组件内部的prev索引状态 const [prevIndex, setPrevIndex] = useState(0); useEffect(() => { // 确保DOM已挂载后再执行逻辑 if (!wrapperRef.current) return; const intervalId = setInterval(() => { const index = uniqueRand(0, combinations.length - 1, prevIndex); const combination = combinations[index]; const wrapper = wrapperRef.current; wrapper.dataset.configuration = combination.configuration; wrapper.dataset.roundness = combination.roundness; setPrevIndex(index); }, 3000); // 组件卸载时清理定时器,防止内存泄漏 return () => clearInterval(intervalId); }, [prevIndex]); // 依赖prevIndex,确保状态更新后定时器逻辑同步 return ( <div className='RO__portfolio' id='portfolio'> {/* 通过ref属性绑定元素 */} <div className='RO__portfolio-content' data-roundness="1" data-configuration="1" ref={wrapperRef} > <div className='RO__portfolio-content_shape'></div> <div className='RO__portfolio-content_shape'></div> <div className='RO__portfolio-content_shape'></div> <div className='RO__portfolio-content_shape'></div> <div className='RO__portfolio-content_shape'></div> <div className='RO__portfolio-content_shape'></div> <div className='RO__portfolio-content_shape'></div> </div> </div> ) } export default Portfolio
关键改动说明
useRef替代原生DOM查询:useRef会在组件挂载后精准指向目标DOM元素,避免DOM未渲染时获取到null。useEffect管控定时器生命周期:确保定时器在DOM挂载后启动,组件卸载时自动清除,避免内存泄漏。useState维护内部状态:将全局prev改为组件内部状态,避免多实例或重复渲染时的变量共享问题,保证逻辑独立性。
内容的提问来源于stack exchange,提问作者Rafael Oliva
相关产品推荐
相关产品推荐

