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

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事件被拦截。按以下步骤修改即可解决:

  1. 阻止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();
    }
  }}
/>
  1. 移除强制设置宽度的逻辑
    原代码中useLayoutEffect会根据文本长度强制设置textarea宽度,这会和resize操作冲突,直接删除这段代码:
// 删掉以下自动设置宽度的代码块
// useLayoutEffect(() => {
//     if (inputRef.current) {
//         inputRef.current.style.width = `${data.label.length * 8}px`;
//     }
// }, [data.label.length]);
  1. 调整textarea基础样式(可选)
    通过CSS给textarea设置最小宽高,避免初始尺寸过小:
.input {
  min-width: 120px;
  min-height: 60px;
  resize: both; /* 默认即为both,可省略 */
}

内容的提问来源于stack exchange,提问作者Tio

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 13:03:31