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

如何将Lexical与React-Hook-Form集成,实现编辑器内容表单提交

解决Lexical编辑器与React-Hook-Form的集成问题

要让Lexical编辑器内容被React-Hook-Form捕获,核心是通过Controller组件的双向绑定同步编辑器状态与表单值,同时优化编辑器的初始化和内容更新逻辑。以下是完整实现方案:

1. 重构MyEditor组件

给编辑器添加回调属性传递内容,修复初始化逻辑避免重复渲染问题:

type LexicalEditorProps = {
  content: string;
  onChange: (value: string) => void; // 新增回调,向父组件传递编辑器内容
};

export default function MyEditor(props: LexicalEditorProps) {
  const [editor] = useLexicalComposerContext();
  const { content, onChange } = props;

  // 初始化编辑器内容
  useEffect(() => {
    if (content) {
      try {
        const parsedState = JSON.parse(content);
        editor.setEditorState(parsedState);
      } catch (e) {
        // 处理无效序列化内容的降级逻辑
        editor.update(() => {
          const root = $getRoot();
          root.clear();
          const paragraph = $createParagraphNode();
          paragraph.append($createTextNode(content));
          root.append(paragraph);
        });
      }
    }
  }, [editor, content]);

  // 监听编辑器变化,序列化后传递给表单
  const handleEditorChange = (editorState: any) => {
    const serializedContent = JSON.stringify(editorState);
    onChange(serializedContent);
  };

  const editorConfig: any = {
    theme: EditorTheme,
    onError(error: any) {
      throw error;
    },
    nodes: [
      HeadingNode,
      ListNode,
      ListItemNode,
      QuoteNode,
      CodeNode,
      CodeHighlightNode,
      TableNode,
      TableCellNode,
      TableRowNode,
      AutoLinkNode,
      LinkNode
    ]
  };

  return (
    <LexicalComposer initialConfig={editorConfig}>
      <div className="editor-container">
        <ToolbarPlugin />
        <div className="editor-inner">
          <RichTextPlugin
            contentEditable={<ContentEditable className="editor-input" />}
            placeholder={<Placeholder />}
            ErrorBoundary={LexicalErrorBoundary}
          />
          <OnChangePlugin onChange={handleEditorChange} />
          <HistoryPlugin />
          <AutoFocusPlugin />
          <CodeHighlightPlugin />
          <ListPlugin />
          <LinkPlugin />
          <AutoLinkPlugin />
          <ListMaxIndentLevelPlugin maxDepth={7} />
          <MarkdownShortcutPlugin transformers={TRANSFORMERS} />
        </div>
      </div>
    </LexicalComposer>
  );
}

2. 完善MyForm组件的Controller配置

通过Controller实现表单与编辑器的双向绑定,适配新增/修改场景:

export function MyForm() {
  const { register, handleSubmit, control, formState: { errors } } = useForm({
    defaultValues: {
      content: dataSet.content || '' // 设置默认值,支持新增(空)和修改(已有内容)
    }
  });

  const onSubmit = (data: any) => {
    console.log(data); // data.content即为编辑器序列化后的内容
    // 此处可执行提交逻辑,如保存到后端
  };

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <Stack spacing={2}>
        <Card>
          <Controller
            control={control}
            name="content"
            render={({ field: { value, onChange } }) => (
              <MyEditor content={value} onChange={onChange} />
            )}
          />
        </Card>
        <Box>
          <Button variant="contained" type="submit">Save</Button>
        </Box>
      </Stack>
    </form>
  );
}

关键改动说明

  • 回调传递内容:给MyEditor新增onChange属性,在编辑器内容变化时序列化状态并传递给父组件,让React-Hook-Form捕获到内容更新。
  • 初始化优化:移除原有的循环更新逻辑,改用editor.setEditorState直接初始化,避免重复插入内容的问题。
  • 双向绑定实现:利用Controller的field对象,将表单值传给编辑器,同时把表单的onChange回调传给编辑器,实现状态同步。
  • 类型明确:将content类型定为字符串,避免类型模糊导致的潜在问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 10:50:46