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

Tiptap结合React-Hook-Form时useEditor依赖致焦点丢失的解决方案

React-Hook-Form 结合 Tiptap 编辑器:解决焦点丢失与状态同步问题

我在用 React-Hook-Form 的 Controller 组件控制 Tiptap 编辑器时遇到了两难问题:

  • 如果把 value 加入 useEditor 的依赖数组,输入时编辑器会频繁丢失焦点;
  • 要是移除 value,焦点能保留,但表单状态又没法和编辑器内容同步。

我的组件代码如下:

interface Props {
    value?: string;
    onChange?: (value: string) => void;
}

const TipTapEditor = ({ value, onChange }: Props) => {
    const editor = useEditor(
        {
            content: cleanText(value || ''),
            onUpdate: ({ editor }) => {
                onChange?.(editor.getHTML());
            },
        },
        [value] // 移除'value'可修复焦点问题但破坏状态同步
    );
};

export default TipTapEditor;

在 React-Hook-Form 的 Controller 中使用方式:

<Controller
    control={control}
    name="my-name"
    render={({ field: { value, onChange } }) => (
        <TipTapEditor value={value} onChange={onChange} />
    )}
/>

解决方案

核心思路是不让编辑器实例因外部 value 变化而频繁重建(这是焦点丢失的根源),改用 useEffect 监听外部值的主动更新,仅在必要时同步编辑器内容,同时保留编辑器自身更新时的表单同步逻辑。

修改后的组件代码:

import { useEffect } from 'react';
import { useEditor } from '@tiptap/react';

interface Props {
    value?: string;
    onChange?: (value: string) => void;
}

const TipTapEditor = ({ value, onChange }: Props) => {
    // 移除依赖数组中的value,确保编辑器实例只创建一次
    const editor = useEditor({
        content: cleanText(value || ''),
        onUpdate: ({ editor }) => {
            onChange?.(editor.getHTML());
        },
    });

    // 监听外部value变化,仅在外部值主动更新时同步编辑器内容
    useEffect(() => {
        if (!editor) return;
        
        const currentContent = editor.getHTML();
        const targetContent = cleanText(value || '');
        
        // 避免编辑器自身更新触发的重复同步
        if (currentContent !== targetContent) {
            editor.commands.setContent(targetContent);
        }
    }, [editor, value]);

    return <div>{editor && <EditorContent editor={editor} />}</div>;
};

export default TipTapEditor;

关键说明

  1. 保留编辑器实例稳定性:移除 useEditor 依赖数组中的 value,编辑器只会初始化一次,彻底解决焦点丢失问题;
  2. 外部值同步逻辑:通过 useEffect 监听外部传入的 value,只有当外部值与编辑器当前内容不一致时,才调用 setContent 更新,避免循环触发;
  3. 表单状态同步:编辑器自身输入时,onUpdate 依然会正常调用 onChange 同步表单状态,双向绑定逻辑不受影响。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 10:32:36