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

React DnD-Kit拖拽结束后输入框获焦但无法输入的问题解决

拖拽结束后输入框获焦但无法输入的问题解决(Next.js + @dnd-kit/core)

问题情况

用Next.js、React、@dnd-kit/core和TypeScript开发时碰到个奇怪的问题:

  • 直接调用testRef?.current?.focus(),输入框能正常获焦并输入内容
  • 但通过useDndMonitor的onDragEnd事件触发focus后,输入框明明显示焦点头像,日志也打印了"focus",就是没法输入
  • 用按钮点击触发focus却完全正常

复现代码:

"use client";

import {
  DragEndEvent,
  useDndMonitor,
  useDraggable,
  useDroppable,
} from "@dnd-kit/core";
import React, { useRef } from "react";

function page() {
  const testRef = useRef(null);

  useDndMonitor({
    onDragEnd: (event: DragEndEvent) => {
      if (testRef.current) {
        console.log("focus");
        (testRef?.current as HTMLInputElement).focus();
      }
    },
  });

  const draggable = useDraggable({
    id: "drag",
  });

  const droppable = useDroppable({
    id: "drop",
  });
  return (
    <div>
      <div
        ref={draggable.setNodeRef}
        {...draggable.listeners}
        {...draggable.attributes}
        className="h-10 w-10 border border-yellow-200"
      >
        drag
      </div>
      <div
        ref={droppable.setNodeRef}
        className="h-10 w-10 border border-green-200"
      >
        drop
      </div>

      <form onSubmit={() => console.log("submit")}>
        <input ref={testRef} defaultValue="default " />
        <input type="submit" />
      </form>
    </div>
  );
}

export default page;

解决方法

把onDragEnd里的focus调用放到setTimeout或者requestAnimationFrame里,延迟到下一个事件循环执行:

修改后的useDndMonitor代码:

useDndMonitor({
  onDragEnd: (event: DragEndEvent) => {
    if (testRef.current) {
      console.log("focus");
      // 用setTimeout延迟执行
      setTimeout(() => {
        (testRef.current as HTMLInputElement).focus();
      }, 0);
      // 或者用requestAnimationFrame,效果类似
      // requestAnimationFrame(() => {
      //   (testRef.current as HTMLInputElement).focus();
      // });
    }
  },
});

根本原因

@dnd-kit在拖拽结束的流程里,会同步执行一系列内部DOM清理和状态重置操作——比如移除拖拽时生成的临时元素、重置鼠标事件监听等。

你在onDragEnd里直接调用focus时,输入框虽然暂时拿到了焦点,但@dnd-kit后续的收尾操作会干扰焦点状态,或者导致浏览器的输入上下文没有正确绑定到输入框上,最终就出现了“有焦点头像但无法输入”的情况。

用setTimeout或requestAnimationFrame把focus操作延后,等@dnd-kit的所有拖拽收尾工作完成后再执行,就能避开这种干扰,让输入框正常接收键盘输入。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 16:05:04