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
相关产品推荐
相关产品推荐

