skip to Main Content

I tried to access the dom to get the height of a specific element in react using useRef() hook, and assign the height of another element to it, so its height would change dynamically based on the height change of the reference element and I used the height.current.clientHeight property but I encountered an error message saying:

TypeError: Cannot read properties of null (reading ‘clientHeight’)

and here is the code:

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

const Navbar = () => {
  const height = useRef(null);
  const [open, setOpen] = useState(false);
  function handleClick() {
    setOpen(!open);
  }
  return (
    <>
      <MenuIcon bgC="bg-white" handle={handleClick} open={open} />
      <div className="w-full relative h-[40%]" ref={height}>
        <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="/"
        />

        <div className="w-full h-full bg-black/40 absolute top-0 lef-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
        className={
          open
            ? `w-auto h-${height.current.clientHeight} 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 h-${height.current.clientHeight} 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;

I tried checking if the "height.current !== null" and if true would assign the value of the clientHeight to another variable, if not would assign "auto" as so:

const hi = height.current ? ${height.current.clientHeight} : "auto"

still getting the same error

I expected it to work fine but it really didn’t

2

Answers


  1. The useRef hook variable doesn’t get the current property immediately. This gets populated after the initial DOM render.

    To get this working, add a useEffect hook with height.current in dependency array.

    Use a flag with useState hook and inside useEffect hook, update the flag.

      const [flag, setFlag] = useState(false);
      useEffect(() => {
         if(height.current) setFlag(true);
      }, [height.current]);
    
    // and use the flag in div class
     <div
         className={
              open && flag
                ? `w-auto h-${height.current.clientHeight}... 
            }
      >
      
    
    Login or Signup to reply.
  2. You can’t get the value of the useRef hook when the component is rendering. You should use the useRef hook after the component is rendered.

    const Navbar = () => {
      const height = useRef(null);
      const [open, setOpen] = useState(false);
    
      function handleClick() {
        setOpen(!open);
      }
    
      useEffect(() => {
        console.log("heightRef.current.clientHeight", height.current.clientHeight);
      }, []);
    
      return (
        <>
          <div onClick={handleClick} open={open}>
            button
          </div>
          <div
            style={{ backgroundColor: "red", height: open ? 100 : 300 }}
            ref={height}
          >
            useref
          </div>
        </>
      );
    };
    

    Maybe it can work for you.

    const Navbar = () => {
      const height = useRef(null);
    
      const [open, setOpen] = useState(false);
      const [heightState, setHeightState] = useState(0);
    
      function handleClick() {
        setOpen(!open);
      }
    
      useEffect(() => {
        // set clientHeight of item when the component is rendered
        setHeightState(height.current.clientHeight);
      }, []);
    
      // prepare value after re-rendering componenet
      const preparedHeight = height.current
        ? height.current.clientHeight
        : heightState;
    
      return (
        <>
          <div onClick={handleClick} open={open}>
            button
          </div>
          <div
            className="height-ref-class"
            style={{ backgroundColor: "red", height: open ? 100 : 300 }}
            ref={height}
          >
            useref {preparedHeight}
          </div>
        </>
      );
    };
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search