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

React中用useRef获取DOM高度触发TypeError问题求助

问题分析与解决方案

错误原因

  1. 首次渲染时ref未绑定DOM:组件第一次渲染时,height.current还未关联到目标DOM元素,值为null,直接访问clientHeight会触发TypeError。即便你定义了hi变量,若在组件渲染阶段(return语句中)直接依赖height.current,首次渲染时依然会因为null值报错。
  2. Tailwind类使用错误:Tailwind的h-*是预设工具类(如h-40对应固定高度),不能直接拼接像素值作为类名,这种写法无法生效,反而可能引入语法问题。

解决步骤

  1. 用useEffect等待ref绑定完成后再获取高度,避免首次渲染的null错误。
  2. 使用ResizeObserver监听参考元素的高度变化,实现动态同步。
  3. 用状态存储高度值,确保组件能响应高度变化重新渲染。
  4. 改用内联样式设置目标元素的高度,替代错误的Tailwind类拼接方式。
  5. 监听图片加载完成事件,因为图片加载会改变父元素高度,需要重新计算。

修改后的完整代码

import React, { useState, useRef, useEffect } from "react";
import Link from "next/link";
import MenuIcon from "./MenuIcon";
import Image from "next/image";
import bg from "../public/bg.jpg";

const Navbar = () => {
  const heightRef = useRef(null);
  const [targetHeight, setTargetHeight] = useState("auto");
  const [open, setOpen] = useState(false);

  function handleClick() {
    setOpen(!open);
  }

  useEffect(() => {
    // 更新高度的通用函数
    const updateHeight = () => {
      if (heightRef.current) {
        setTargetHeight(`${heightRef.current.clientHeight}px`);
      } else {
        setTargetHeight("auto");
      }
    };

    // 首次挂载后获取初始高度
    updateHeight();

    // 监听元素高度变化
    const observer = new ResizeObserver(updateHeight);
    if (heightRef.current) {
      observer.observe(heightRef.current);
    }

    // 组件卸载时清理监听
    return () => {
      if (heightRef.current) {
        observer.unobserve(heightRef.current);
      }
    };
  }, []);

  return (
    <>
      <MenuIcon bgC="bg-white" handle={handleClick} open={open} />
      <div className="w-full relative h-[40%]" ref={heightRef}>
        <nav className="xs:max-md:hidden flex z-20 justify-between md:max-lg:justify-end md:max-lg:gap-24 text-white bg-transparent backdrop-blur-lg  py-3 px-6 ">
          <div className="hover:text-gray-300 hover:text-[20px] ease-in duration-100">
            <Link href="/">About me</Link>
          </div>
          <div className="hover:text-gray-300 hover:text-[20px] ease-in duration-100">
            <Link href="/">My skills</Link>
          </div>
          <div className="hover:text-gray-300 hover:text-[20px] ease-in duration-100">
            <Link href="/">Portfolio</Link>
          </div>
          <div className="hover:text-gray-300 hover:text-[20px] ease-in duration-100">
            <Link href="/">Contacts</Link>
          </div>
        </nav>

        <Image
          src={bg}
          layout="responsive"
          objectFit="contain"
          width={400}
          height={400}
          alt="background"
          // 图片加载完成后重新计算高度
          onLoad={updateHeight}
        />

        <div className="w-full h-full bg-black/40 absolute top-0 left-0 right-0">
          <h1 className="text-white w-[75%] font-Neo font-[12px] box-border text-2xl mx-auto text-center translate-y-[140px]">
            Hi there! My name is Alharith and I am a front-end developer.
          </h1>
        </div>
      </div>
      <div
        // 用内联样式设置动态高度
        style={{ height: targetHeight }}
        className={
          open
            ? "w-auto box-border px-12 bg-blue-400 backdrop-blur-sm fixed top-0 right-0 translate-x-0 duration-300 ease-in flex flex-col items-center justify-around text-2xl"
            : "w-auto px-12 py-[30px] bg-transparent backdrop-blur-sm fixed top-0 right-0 translate-x-[100%] duration-300 ease-in flex flex-col items-center justify-around text-2xl"
        }
      >
        <div className="w-full flex flex-col justify-around items-center h-[50%] gap-8 text-2xl font-Neo">
          <div className="font-Neo text-2xl hover:text-[20px] hover:text-gray-100 duration-100 ease-in">
            <Link href="/">About me</Link>
          </div>
          <div className="font-Neo text-2xl hover:text-[20px] hover:text-gray-100 duration-100 ease-in">
            <Link href="/">My Skills</Link>
          </div>
          <div className="font-Neo text-2xl hover:text-[20px] hover:text-gray-100 duration-100 ease-in">
            <Link href="/">Portfolio</Link>
          </div>
          <div className="font-Neo text-2xl hover:text-[20px] hover:text-gray-100 duration-100 ease-in">
            <Link href="/">Contacts</Link>
          </div>
        </div>
      </div>
    </>
  );
};

export default Navbar;

关键修改说明

  • 将height重命名为heightRef,更符合ref变量的命名规范。
  • 新增targetHeight状态存储动态高度,确保组件能响应高度变化更新UI。
  • 用useEffect和ResizeObserver实现高度的初始获取和动态监听,避免null错误。
  • 给Image添加onLoad事件,确保图片加载完成后重新计算高度。
  • 用内联样式style={{ height: targetHeight }}设置目标元素高度,替代无效的Tailwind类拼接。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 17:05:57