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

React中实现仅在Div文本溢出时显示Show More/Show Less

解决React组件中文本未溢出时仍显示Show More链接的问题

我明白你遇到的困扰——本来只想在文本真的超出容器时显示展开/收起按钮,结果现在不管文本长短都冒出来了,而且尝试用ref判断溢出还碰到了Cannot read property 'style' of null的错误。别担心,我来帮你一步步搞定这个问题。

错误原因分析

你遇到的这个null报错,核心原因是组件首次渲染时,ref还没绑定到DOM元素上,你直接在render里调用checkOverflow,此时ref.current是null,自然访问不了style属性。另外,就算ref绑定成功了,在render里直接执行判断函数还可能引发重复渲染的无限循环,因为判断逻辑可能间接触发状态更新。

完整解决方案

我们需要调整思路:用useRef获取DOM元素,在组件挂载后(以及文本/容器尺寸变化时)检查溢出状态,把结果存在状态里,最后根据这个状态来控制按钮的显示。

完整代码实现

React组件代码

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 textContainerRef = useRef(null);

  // 切换展开/收起状态
  const toggleShowMore = () => {
    setShowMore(!showMore);
  };

  // 检查文本是否溢出的核心函数
  const checkOverflow = () => {
    // 先判断ref是否存在,避免null错误
    if (!textContainerRef.current) return false;
    const el = textContainerRef.current;
    // 保存原始overflow样式,避免临时修改影响显示
    const originalOverflow = el.style.overflow;
    el.style.overflow = "hidden";
    // 判断横向或纵向是否溢出
    const overflowed = el.clientWidth < el.scrollWidth || el.clientHeight < el.scrollHeight;
    // 恢复原始样式
    el.style.overflow = originalOverflow;
    return overflowed;
  };

  // 在合适的时机更新溢出状态
  useEffect(() => {
    const updateOverflowStatus = () => {
      setIsOverflowing(checkOverflow());
    };
    // 组件挂载后首次检查
    updateOverflowStatus();
    // 监听窗口resize,防止容器尺寸变化导致判断失效
    window.addEventListener("resize", updateOverflowStatus);
    // 组件卸载时清理监听
    return () => {
      window.removeEventListener("resize", updateOverflowStatus);
    };
  }, [props.text]); // 当传入的文本变化时,重新检查溢出

  return (
    <div className="wrapper">
      <div
        ref={textContainerRef}
        className={`text-container ${showMore ? "expanded" : ""}`}
      >
        {props.text}
      </div>
      {/* 只有当文本确实溢出时,才显示切换链接 */}
      {isOverflowing && (
        <span className="toggle-link" onClick={toggleShowMore}>
          {showMore ? "Show Less" : "Show More"}
        </span>
      )}
    </div>
  );
}

对应的CSS样式

.wrapper {
  width: 250px;
  background-color: #eaeaea;
  padding: 8px;
}

.text-container {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  transition: all 0.2s ease;
}

/* 展开时取消单行限制,显示全部文本 */
.text-container.expanded {
  white-space: normal;
  text-overflow: unset;
}

.toggle-link {
  color: #0066cc;
  cursor: pointer;
  margin-top: 8px;
  display: inline-block;
}

.toggle-link:hover {
  text-decoration: underline;
}

关键优化点说明

  • 用useRef替代createRef:函数组件中推荐使用useRef,它在组件整个生命周期内保持同一个引用,不会每次render都创建新的ref对象。
  • useEffect控制执行时机:确保在DOM挂载完成后再执行溢出判断,避免ref为null的问题;同时监听窗口resize,保证容器尺寸变化时能重新判断。
  • 状态存储溢出结果:把溢出状态存在isOverflowing中,render时直接读取这个状态,避免在render阶段执行有副作用的函数,防止无限循环。
  • CSS类切换更清晰:用expanded类统一控制文本展开/收起的样式,比多个类切换更易维护。

内容的提问来源于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:34:09