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

Next.js集成React Quill出现Tab重复触发问题如何修复

Next.js下react-quill按Tab键重复缩进问题修复

问题表现

在Next.js项目中安装使用react-quill,基础富文本功能可正常运行,但按下Tab键时会触发多次重复缩进,效果如下:
Tab重复缩进bug截图
初始问题代码如下:

import { useState } from "react";
import dynamic from "next/dynamic";
const ReactQuill = dynamic(() => import("react-quill"), { ssr: false });
import "react-quill/dist/quill.snow.css";

function App() {
  const [value, setValue] = useState("");
  const modules = {
    toolbar: [
      [{ header: "1" }, { header: "2" }, { font: [] }],
      [{ size: [] }],
      ["bold", "italic", "underline", "strike", "blockquote"],
      [
        { list: "ordered" },
        { list: "bullet" },
        { indent: "-1" },
        { indent: "+1" },
      ],
      ["link", "image", "video"],
      ["clean"],
    ],
    clipboard: {
      matchVisual: false,
    },
  };

  return (
    <div>
      <ReactQuill
        value={value}
        onChange={setValue}
        theme='snow'
        modules={modules}
      />
    </div>
  );
}

export default App;

问题原因

两个核心问题导致该bug:

  • modules配置直接写在组件函数内部,每次输入触发组件重渲染时都会生成全新的modules对象,导致Quill重复初始化模块、重复绑定Tab键事件监听,一次按键会触发多次缩进逻辑
  • Quill默认的Tab键事件绑定没有阻止冒泡,在Next.js的SSR/CSR混合渲染场景下容易出现事件重复触发的问题

修复方案

按以下两点调整代码即可解决:

  • 将modules配置移到组件外部(或用useMemo缓存),避免重渲染时重复初始化模块
  • 新增keyboard模块配置,手动接管Tab、Shift+Tab的缩进逻辑,阻止默认事件冒泡

修复后的完整代码:

import { useState } from "react";
import dynamic from "next/dynamic";
const ReactQuill = dynamic(() => import("react-quill"), { ssr: false });
import "react-quill/dist/quill.snow.css";

// 移到组件外部,避免重渲染生成新配置
const modules = {
  toolbar: [
    [{ header: "1" }, { header: "2" }, { font: [] }],
    [{ size: [] }],
    ["bold", "italic", "underline", "strike", "blockquote"],
    [
      { list: "ordered" },
      { list: "bullet" },
      { indent: "-1" },
      { indent: "+1" },
    ],
    ["link", "image", "video"],
    ["clean"],
  ],
  clipboard: {
    matchVisual: false,
  },
  // 新增键盘事件配置,接管Tab逻辑
  keyboard: {
    bindings: {
      tab: {
        key: 9,
        handler(range) {
          // 执行单次缩进
          this.quill.format("indent", "+1", true, "user");
          // 阻止默认逻辑和事件冒泡,避免重复触发
          return false;
        },
      },
      "shift tab": {
        key: 9,
        shiftKey: true,
        handler(range) {
          // 执行单次反向缩进
          this.quill.format("indent", "-1", true, "user");
          return false;
        },
      },
    },
  },
};

function App() {
  const [value, setValue] = useState("");

  return (
    <div>
      <ReactQuill
        value={value}
        onChange={setValue}
        theme="snow"
        modules={modules}
      />
    </div>
  );
}

export default App;

调整后按Tab/Shift+Tab只会触发单次缩进/反向缩进,不会再出现重复缩进的问题。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 07:42:13