React中用useRef获取DOM高度触发TypeError问题求助
问题分析与解决方案
错误原因
- 首次渲染时ref未绑定DOM:组件第一次渲染时,
height.current还未关联到目标DOM元素,值为null,直接访问clientHeight会触发TypeError。即便你定义了hi变量,若在组件渲染阶段(return语句中)直接依赖height.current,首次渲染时依然会因为null值报错。 - Tailwind类使用错误:Tailwind的
h-*是预设工具类(如h-40对应固定高度),不能直接拼接像素值作为类名,这种写法无法生效,反而可能引入语法问题。
解决步骤
- 用
useEffect等待ref绑定完成后再获取高度,避免首次渲染的null错误。 - 使用
ResizeObserver监听参考元素的高度变化,实现动态同步。 - 用状态存储高度值,确保组件能响应高度变化重新渲染。
- 改用内联样式设置目标元素的高度,替代错误的Tailwind类拼接方式。
- 监听图片加载完成事件,因为图片加载会改变父元素高度,需要重新计算。
修改后的完整代码
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
相关产品推荐
相关产品推荐

