React切换textarea模式后blobRef为null:高度自适应异常求助
问题原因及解决方案
为什么切换模式后blobRef变成null?
React的状态更新是异步的。在toggleChecklist函数中,调用setChecklist((prev) => !prev)后,checklist的新值不会立刻生效——此时执行if (checklist)代码块时,checklist还是切换前的旧值(也就是当前处于checklist模式,值为true)。
这时候组件还没完成重新渲染,单个textarea还没被挂载到DOM上,blobRef自然还没被赋值,所以blobRef.current是null。只有当组件重新渲染完成,checklist变为false,dataArea()返回的单个textarea才会被渲染,blobRef才会指向对应的DOM元素。
解决方案
方案1:用useEffect监听状态变化,在组件渲染完成后操作
把原来toggleChecklist里操作blobRef的逻辑,移到监听checklist状态的useEffect中,确保组件已经重新渲染、单个textarea挂载完成后再执行:
import { useEffect, useRef, useState } from 'react'; // ... 其他代码 const blobRef = useRef(null); // 新增useEffect监听checklist状态 useEffect(() => { // 当从checklist模式切换到单个textarea模式时 if (!checklist) { // 此时textarea已挂载,blobRef.current可用 blobRef.current?.dispatchEvent(new Event('input')); } }, [checklist]); function toggleChecklist() { setChecklist((prevChecklist) => !prevChecklist); if (checklist) { const n = '\n'; // 直接用换行符更简洁 setData(checklistData.reduce((p, c) => p.concat(c.data + n), '')); // 移除这里的blobRef操作 } } // ... 其他代码
方案2:抽离高度调整逻辑,避免依赖input事件
把自动增高的逻辑抽成独立函数,无论是用户输入还是状态更新后,都可以直接调用,更可靠:
function adjustTextareaHeight(element) { if (!element) return; element.style.height = '0'; element.style.height = element.scrollHeight + 'px'; } // 在handleInput中调用 function handleInput(e, i) { const element = e.target; // ... 原有的状态更新逻辑 adjustTextareaHeight(element); } // 在useEffect中调用,处理状态更新后的高度调整 useEffect(() => { if (!checklist) { adjustTextareaHeight(blobRef.current); } }, [checklist, data]); // 监听data变化,确保合并后的内容能触发高度调整
这样即使不手动触发input事件,也能保证textarea的高度自动适配内容。
内容的提问来源于stack exchange,提问作者werdnanoslen
相关产品推荐
相关产品推荐

