React-Flow节点中如何使用textarea并实现拖拽调整输入框大小
问题
在React-Flow应用的节点中,想用textarea替代input,并通过textarea右下角的默认拖拽图标调整输入框大小。将input改为textarea后,拖拽图标可见,但拖拽时整个节点会移动,无法调整textarea大小,请问如何解决?
现有代码(MindMapNode.jsx)
import {useLayoutEffect, useEffect, useRef} from 'react'; import {Handle, Position} from 'reactflow'; import useStore from '../store'; import DragIcon from './DragIcon'; function MindMapNode({id, data}) { const inputRef = useRef(null); const updateNodeLabel = useStore((state) => state.updateNodeLabel); useEffect(() => { setTimeout(() => { inputRef.current?.focus({preventScroll: true}); }, 1); }, []); useLayoutEffect(() => { if (inputRef.current) { inputRef.current.style.width = `${data.label.length * 8}px`; } }, [data.label.length]); return ( <> <div className="inputWrapper"> <div className="dragHandle"> <DragIcon/> </div> <textarea value={data.label} onChange={(evt) => updateNodeLabel(id, evt.target.value)} className="input" ref={inputRef} /> </div> <Handle type="target" position={Position.Top}/> <Handle type="source" position={Position.Top}/> </> ); } export default MindMapNode;
环境版本
- node: 20.10.0
- react: 18.2.0
- reactflow: 11.10.1
解决方案
问题根源是React Flow节点默认会捕获所有拖拽事件用于节点移动,导致textarea的resize事件被拦截。按以下步骤修改即可解决:
- 阻止resize手柄的事件冒泡
给textarea添加onMouseDown事件,判断点击区域是否为右下角的resize手柄,若是则阻止事件向上冒泡,避免触发节点移动:
<textarea value={data.label} onChange={(evt) => updateNodeLabel(id, evt.target.value)} className="input" ref={inputRef} onMouseDown={(e) => { // 定位textarea右下角的resize手柄区域(约16px范围) const rect = e.target.getBoundingClientRect(); const isResizeHandle = e.clientX > rect.right - 16 && e.clientY > rect.bottom - 16; if (isResizeHandle) { e.stopPropagation(); } }} />
- 移除强制设置宽度的逻辑
原代码中useLayoutEffect会根据文本长度强制设置textarea宽度,这会和resize操作冲突,直接删除这段代码:
// 删掉以下自动设置宽度的代码块 // useLayoutEffect(() => { // if (inputRef.current) { // inputRef.current.style.width = `${data.label.length * 8}px`; // } // }, [data.label.length]);
- 调整textarea基础样式(可选)
通过CSS给textarea设置最小宽高,避免初始尺寸过小:
.input { min-width: 120px; min-height: 60px; resize: both; /* 默认即为both,可省略 */ }
内容的提问来源于stack exchange,提问作者Tio
相关产品推荐
相关产品推荐

