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

React函数组件检测div溢出报错:Cannot read property 'style' of null

问题分析与解决方案

你遇到的Cannot read property 'style' of null错误,核心原因是组件初始渲染时,DOM元素还未挂载到页面,此时ref.current是null,你直接在render阶段调用checkOverflow(),自然会访问到null的style属性导致报错。

下面针对两种方案分别给出修复后的代码,并解释关键改进点:


方案1:使用useRef(函数组件推荐替代createRef)

函数组件中更推荐用useRef(它会保持引用稳定,不像createRef每次渲染都创建新对象),结合useEffect在DOM挂载后再执行溢出检测:

import React, { useState, useRef, useEffect } from "react";
import "./styles.css";

export default function App(props) {
  const [showMore, setShowMore] = useState(false);
  const [isOverflowing, setIsOverflowing] = useState(false);
  const contentRef = useRef(null);

  const toggleShowMore = () => {
    setShowMore(!showMore);
  };

  const checkOverflow = () => {
    const el = contentRef.current;
    if (!el) return false; // 先判断元素是否存在,做容错处理

    // 临时修改overflow确保检测准确(如果你的容器默认不是hidden的话)
    const originalOverflow = el.style.overflow;
    if (!originalOverflow || originalOverflow === "visible") {
      el.style.overflow = "hidden";
    }

    const hasOverflow = el.clientWidth < el.scrollWidth || el.clientHeight < el.scrollHeight;
    el.style.overflow = originalOverflow; // 恢复原样式
    return hasOverflow;
  };

  useEffect(() => {
    // DOM挂载后执行检测,同时监听文本变化、展开/收起状态、窗口resize
    const updateOverflowStatus = () => {
      setIsOverflowing(checkOverflow());
    };

    updateOverflowStatus();
    window.addEventListener("resize", updateOverflowStatus);
    
    // 组件卸载时移除监听
    return () => {
      window.removeEventListener("resize", updateOverflowStatus);
    };
  }, [props.text, showMore]);

  return (
    <>
      <div 
        ref={contentRef} 
        className={showMore ? "container-nowrap" : "container"}
      >
        {props.text}
      </div>
      {isOverflowing && (
        <span className="link" onClick={toggleShowMore}>
          {showMore ? "show less" : "show more"}
        </span>
      )}
    </>
  );
}

方案2:使用forwardRef

子组件同样需要通过useEffect延迟检测,确保ref已绑定到DOM元素:

子组件

import React, { useState, useEffect } from "react";

export const App = React.forwardRef((props, ref) => {
  const [showMore, setShowMore] = useState(false);
  const [isOverflowing, setIsOverflowing] = useState(false);

  const toggleShowMore = () => {
    setShowMore(!showMore);
  };

  const checkOverflow = () => {
    const el = ref.current;
    if (!el) return false;

    const originalOverflow = el.style.overflow;
    if (!originalOverflow || originalOverflow === "visible") {
      el.style.overflow = "hidden";
    }

    const hasOverflow = el.clientWidth < el.scrollWidth || el.clientHeight < el.scrollHeight;
    el.style.overflow = originalOverflow;
    return hasOverflow;
  };

  useEffect(() => {
    const updateOverflow = () => {
      setIsOverflowing(checkOverflow());
    };

    updateOverflow();
    window.addEventListener("resize", updateOverflow);
    return () => {
      window.removeEventListener("resize", updateOverflow);
    };
  }, [props.text, showMore]);

  return (
    <>
      <div 
        ref={ref} 
        className={showMore ? "container-nowrap" : "container"}
      >
        {props.text}
      </div>
      {isOverflowing && (
        <span className="link" onClick={toggleShowMore}>
          {showMore ? "show less" : "show more"}
        </span>
      )}
    </>
  );
});

父组件(无需修改)

import React from "react";
import ReactDOM from "react-dom";
import { App } from "./App";

const rootElement = document.getElementById("root");
const contentRef = React.createRef();

ReactDOM.render(
  <React.StrictMode>
    <App 
      ref={contentRef} 
      text="Start editing to see some magic happen! Click show more to expand and show less to collapse the text" 
    />
  </React.StrictMode>,
  rootElement
);

关键改进说明

  1. 延迟检测时机:用useEffect确保DOM挂载后再执行溢出检测,避免初始渲染时ref.current为null的问题。
  2. 状态托管溢出结果:把溢出状态存在useState中,而不是在render阶段实时计算,避免重复执行检测逻辑,也保证渲染的稳定性。
  3. 添加resize监听:窗口大小变化可能导致溢出状态改变,监听resize事件可以实时更新状态。
  4. 容错处理:在checkOverflow中先判断元素是否存在,避免意外报错。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.07 00:27:36