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

React TypeError: wrapper is null报错及定时器间隔异常求助

解决React中TypeError: wrapper is null的问题

问题原因

  1. DOM未挂载时获取元素:组件函数执行时,return中的DOM还未渲染到页面,此时document.getElementById("wrapper")返回null,直接调用wrapper.dataset必然报错。
  2. 未清理定时器:组件卸载后setInterval不会自动停止,会造成内存泄漏,还可能在组件卸载后继续执行引发错误。
  3. 全局变量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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 02:45:14