如何将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
相关产品推荐
相关产品推荐

