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

React项目出现Variable is null报错,未创建对应变量求排查

问题分析与解决办法

你遇到的「Variable is null」报错,核心原因是React组件的执行顺序问题:组件函数执行时,返回的JSX还没挂载到浏览器DOM中,这时候直接用document.getElementById('left-side')根本拿不到元素,自然返回null。

至于动画能正常运行,是因为组件挂载完成后,定时器和鼠标/触摸事件里的switchSides会再次执行——这时DOM元素已经存在,但初始执行的那一次已经抛出错误了。


1. 用React规范方式获取DOM元素

别在组件顶层直接调用document.getElementById,改用React提供的useRef钩子,配合useEffect在组件挂载后再操作DOM:

修正后的Header.js代码

import React, { useEffect, useRef } from 'react';

const Header = () => {
    const leftRef = useRef(null);
    const rightRef = useRef(null);
    let isLeftVisible = true;
    let timer = null;

    const switchSides = () => {
        isLeftVisible = !isLeftVisible;
        const left = leftRef.current;
        if (!left) return; // 加判断避免意外报错

        if (isLeftVisible) {
            left.style.width = "0%";
        } else {
            left.style.width = "100%";
        }
    }

    useEffect(() => {
        // 组件挂载完成后再操作DOM
        const left = leftRef.current;
        const right = rightRef.current;
        if (!left || !right) return;

        left.style.transition = "width 1.5s";
        right.style.transition = "width 1.5s";

        // 初始化定时器
        timer = setInterval(switchSides, 3000);

        // 定义事件处理函数
        const resetTimer = () => {
            clearInterval(timer);
            timer = setInterval(switchSides, 3000);
        }

        document.addEventListener("mousemove", resetTimer);
        document.addEventListener("touchstart", resetTimer);

        // 组件卸载时清理定时器和事件监听,避免内存泄漏
        return () => {
            clearInterval(timer);
            document.removeEventListener("mousemove", resetTimer);
            document.removeEventListener("touchstart", resetTimer);
        };
    }, []); // 空依赖数组,仅在挂载/卸载时执行

    return (
        <>
            {/* 将ref绑定到对应DOM元素 */}
            <div id="left-side" className="side" ref={leftRef}>
                <h2 className="title">
                    Sometimes a simple header is 
                    <span className="fancy">better</span>      
                </h2>
            </div>
            <div id="right-side" className="side" ref={rightRef}>
                <h2 className="title">
                    Sometimes a simple header is  
                    <span className="fancy">worse</span>     
                </h2>
            </div>

            <a id="source-link" className="meta-link" href="https://superlist.com" target="_blank" rel="noopener noreferrer">
                <i className="fa-solid fa-link"></i>
                <span className="roboto-mono">Source</span>
            </a>
        </>
    );
};

export default Header;

注意:React的JSX语法中,要用className代替原生HTML的class。


2. 解决「删代码仍报错」的问题

这种情况基本是缓存导致的,按以下步骤操作:

  • 重启React开发服务器(关闭npm start后重新启动)
  • 强制刷新浏览器(快捷键Ctrl+Shift+R / Cmd+Shift+R)
  • 检查是否有其他文件仍在引用旧的代码逻辑

3. 仅留HTML仍报错的原因

之前的代码添加了全局事件监听(mousemove、touchstart)和定时器,这些逻辑会留在浏览器内存中——即使你修改了组件代码,未清理的旧事件回调仍会执行,继续尝试访问不存在的left变量。上面修正后的代码添加了卸载时的清理逻辑,就能彻底解决这个问题。

内容的提问来源于stack exchange,提问作者sappho7124

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 14:19:51