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

如何在react-hook-form中实现SlateJS编辑器自动聚焦与表单重置

解决SlateJS与react-hook-form集成的聚焦和重置问题

核心问题分析

你的代码存在语法错误+缺少value同步逻辑,直接导致聚焦和重置功能失效:

  • CustomEditor的forwardRef参数解构错误,无法正确接收props与ref
  • CustomEditorController中ref回调存在语法错误
  • Slate的initialValue仅在首次渲染生效,未监听外部value变化同步编辑器内容

步骤1:修复基础语法错误

修正CustomEditor的参数结构

forwardRef的第一个参数是完整props对象,而非单独解构的属性:

const CustomEditor = React.forwardRef<any, TextEditorProps>(
  ({ name, value, onValueChange }, ref) => { // 修正:props为整体对象
    const editor: MyEditor = useMemo(() => withHistory(withReact(createEditor())), []);

    useImperativeHandle(ref, () => ({
      focus: () => {
        console.log("set focus via imperative handle");
        ReactEditor.focus(editor);
      },
    }));

    // 后续逻辑...
  }
);

修正CustomEditorController的ref回调

<CustomEditor
  ref={(el: any) => field.ref(el)} // 修正:括号匹配错误
  name={field.name}
  value={field.value}
  onValueChange={field.onChange}
/>

步骤2:实现表单重置同步

Slate的initialValue仅在编辑器初始化时加载内容,react-hook-form调用reset()时,外部value更新但编辑器不会自动同步。需通过useEffect监听value变化,手动重置编辑器内容:

const CustomEditor = React.forwardRef<any, TextEditorProps>(
  ({ name, value, onValueChange }, ref) => {
    const editor: MyEditor = useMemo(() => withHistory(withReact(createEditor())), []);

    // 监听外部value变化,同步编辑器内容
    useEffect(() => {
      // 跳过初始渲染的重复执行
      if (!editor.children.length) return;
      // 对比当前编辑器内容与目标value,不同则重置
      const currentContent = JSON.stringify(editor.children);
      const targetContent = JSON.stringify(value);
      if (currentContent !== targetContent) {
        // 清空编辑器并插入新内容
        Transforms.delete(editor, {
          at: {
            anchor: Editor.start(editor, []),
            focus: Editor.end(editor, []),
          },
        });
        Transforms.insertNodes(editor, value);
      }
    }, [editor, value]);

    useImperativeHandle(ref, () => ({
      focus: () => {
        ReactEditor.focus(editor);
      },
    }));

    return (
      <Slate
        editor={editor}
        initialValue={value}
        onValueChange={onValueChange}
      >
        <Editable name={name} />
      </Slate>
    );
  }
);

步骤3:验证聚焦功能

修正后,react-hook-form的initialFocus或setFocus可通过field.ref调用你暴露的focus方法,激活Slate编辑器聚焦。示例调用代码:

// 在表单组件中使用setFocus触发聚焦
const { setFocus } = useFormContext();

const handleFocusEditor = () => {
  setFocus('editor');
};

关键注意点

  • 确保useImperativeHandle正确暴露focus方法,且field.ref绑定到组件ref上
  • Slate编辑器内容为内部状态,外部value变化必须手动同步,不能依赖initialValue
  • 内容对比用JSON.stringify是简易方案,复杂场景可替换为Slate内置的Editor.equals方法优化

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 22:20:11