React实现textarea自动增长后无法自动收缩如何解决
Textarea高度双向自适应修复方案
你现有代码仅能增高无法收缩的核心原因有三点:
- 高度重置逻辑兼容性差,设为
0px的方式在部分场景下无法让浏览器正确计算收缩后的内容高度 - 仅在用户输入时触发高度计算,组件初始挂载、外部赋值/清空内容时不会执行自适应逻辑
- 组件接收的
className参数未合并到渲染节点,易出现自定义样式失效导致的高度计算偏差
修正后的样式代码
保留原有基础样式,可按需配置最小高度避免空内容时高度塌缩,也可添加最大高度限制:
.textarea { resize: none; overflow: hidden; box-sizing: border-box; /* 按需自定义最小高度 */ min-height: 40px; /* 按需自定义最大高度,超出后显示滚动条 */ /* max-height: 200px; */ }
修正后的组件实现
引入Ref实例绑定textarea节点,封装独立的自适应方法,覆盖所有触发高度变化的场景:
import { useRef, useEffect, useCallback } from 'react' // 按你的项目实际路径导入样式文件 import styles from './textarea.module.css' export default function Textarea({ className, onChange, defaultValue, value, ...attrs }) { const textareaRef = useRef(null) // 封装高度自适应逻辑 const adjustHeight = useCallback(() => { const el = textareaRef.current if (!el) return // 先重置高度为auto,触发浏览器重排收回多余高度 el.style.height = 'auto' // 赋值为内容实际高度,完成自适应 el.style.height = `${el.scrollHeight}px` }, []) // 组件挂载、受控值/默认值变更时自动调整高度 useEffect(() => { adjustHeight() }, [value, defaultValue, adjustHeight]) const handleInput = (e) => { adjustHeight() onChange?.(e) } return ( <textarea {...attrs} ref={textareaRef} value={value} defaultValue={defaultValue} onInput={handleInput} // 合并内置样式与外部传入的自定义类名 className={`${styles.textarea} ${className ?? ''}`.trim()} /> ) }
关键逻辑说明
- 高度重置阶段使用
height: auto替代原来的height: 0px,兼容性更好,不会因为高度骤降触发页面滚动条跳动,同时能保证内容减少时浏览器可以正确计算收缩后的基准高度 - 自适应逻辑同时覆盖了用户输入、初始渲染、外部赋值/清空内容三类场景,不会出现内容变了高度没更新的问题
- 样式类名合并逻辑保证外部自定义的padding、border、min-height等样式可以正常生效,不会干扰高度计算
内容的提问来源于stack exchange,提问作者Lance Pollard
相关产品推荐
相关产品推荐

