如何将 Lexical 与 React-Hook-Form 集成以提交编辑器作为输入

Hap*_*ala 7 text-editor rich-text-editor reactjs react-hook-form lexicaljs

当我尝试制作博客时,我无法通过表单中的编辑器。我找到了这个:

DraftJS React-Hook-Form - 提交编辑器作为输入

但似乎 LexicalRichTextEditor 没有这样的标签可以传递。谁能帮我?如何传递属性来实现添加内容和修改内容功能?

type LexicalEditorProps = {
    //config: Parameters<typeof LexicalComposer>["0"]["initialConfig"];
    content: any;
};

export default function MyEditor(props: LexicalEditorProps) {
    const [ editor ] = useLexicalComposerContext();
    const editorStateRef = useRef();
    const [saveContent, setSaveContent] = useState('');
    const editorConfig: any = {
        // The editor theme
        theme: EditorTheme,
        // Handling of errors during update
        onError(error: any) {
            throw error;
        },
        editorState: props.content,
        // Any custom nodes go here
        nodes: [
            HeadingNode,
            ListNode,
            ListItemNode,
            QuoteNode,
            CodeNode,
            CodeHighlightNode,
            TableNode,
            TableCellNode,
            TableRowNode,
            AutoLinkNode,
            LinkNode
        ]
    };

    useEffect(()=>{
        if(editorStateRef.current){
            setSaveContent(JSON.stringify(editorStateRef.current));
        }
        editor.update(()=>{
            const root = $getRoot();
            const selection = $getSelection();
            const paragraphNode = $createParagraphNode();
            const textNode = $createTextNode(saveContent);

            paragraphNode.append(textNode);
            root.append(paragraphNode);

        });
    },[saveContent]);
    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={(editorState:any) => editorStateRef.current = editorState} />
                    <HistoryPlugin />
                    <AutoFocusPlugin />
                    <CodeHighlightPlugin />
                    <ListPlugin />
                    <LinkPlugin />
                    <AutoLinkPlugin />
                    <ListMaxIndentLevelPlugin maxDepth={7} />
                    <MarkdownShortcutPlugin transformers={TRANSFORMERS} />
                </div>
            </div>
        </LexicalComposer>
    );
}

export function MyForm(){
 const {register, handleSubmit, control, formState: {errors}} = useForm();
    const onSubmit = ( data:any) => {      
        console.log(data);
    };
 return (
   <form onSubmit={handleSubmit(onSubmit)}>
                <Stack spacing={2}>                                      
                    <Card>
                        <Controller control={control} name="content" render={()=> (
                            <MyEditor content={dataSet.content} />
                        )} />
                    </Card>
                    <Box>
                        <Button variant="contained" type="submit">Save</Button>
                    </Box>
                </Stack>
            </form>
 );
}
Run Code Online (Sandbox Code Playgroud)

Hap*_*ala 6

我找到了解决方案,但这不是我做的,而是其他伟大的人帮助我解决了这个问题,并希望能够帮助其他人。 https://codesandbox.io/s/purple-water-xf50bi?file=/src/App.tsx

更新:删除 if (editorRef.current !== undefined) 语句并将字段内容附加到数据

export default function App() {
  const schema = yup
    .object({
      title: yup.string().required(),
      category: yup.string().required(),
      tags: yup.array().required()
    })
    .required();
  const { register, handleSubmit } = useForm({
    resolver: yupResolver(schema)
  });

  //Get Editor State
  const editorRef: any = useRef();
  const onSubmit = (data: any) => {
    data.content= JSON.stringify(editorRef.current.getEditorState())
    console.log(data);
  };
  
  //if (editorRef.current !== undefined) {
  // if (editorRef.current !== null) {
  //    const latestEditorState = editorRef.current.getEditorState();
  //    const textContent = latestEditorState.read(() =>
  //      //You could change getTextContent() for your purpose
  //      $getRoot().getTextContent()
  //    );
  //    console.log(textContent);
  //  }
  //}
  return (
    <div className="App">
      <form onSubmit={handleSubmit(onSubmit)}>
        <Stack spacing={2}>
          <input {...register("title")} type="text" placeholder="Title" />
          <input {...register("category")} type="text" placeholder="Category" />
          <input type="" placeholder="Tags" />
          <select {...register("tags")} id="tags" multiple>
            <option value="nginx">nginx</option>
            <option value="java">java</option>
            <option value="react">react</option>
            <option value="mui">mui</option>
          </select>
          <Card elevation={3}>
            <MyEditor ref={editorRef} />
          </Card>
          <button type="submit">Save</button>
        </Stack>
      </form>
    </div>
  );
}
Run Code Online (Sandbox Code Playgroud)

我的编辑器.tsx


function Placeholder() {
  return <div className="editor-placeholder">Enter some rich text...</div>;
}

const editorConfig: any = {
  // The editor theme
  theme: EditorTheme,
  // Handling of errors during update
  onError(error: any) {
    throw error;
  },
  // Any custom nodes go here
  nodes: [
    HeadingNode,
    ListNode,
    ListItemNode,
    QuoteNode,
    CodeNode,
    CodeHighlightNode,
    TableNode,
    TableCellNode,
    TableRowNode,
    AutoLinkNode,
    LinkNode
  ]
};

// ADDED THIS:
const EditorCapturePlugin = React.forwardRef((props: any, ref: any) => {
  const [editor] = useLexicalComposerContext();
  useEffect(() => {
    ref.current = editor;
    return () => {
      ref.current = null;
    };
  }, [editor, ref]);

  return null;
});

export const MyEditor = React.forwardRef((props: any, ref: any) => {
  return (
    <LexicalComposer initialConfig={editorConfig}>
      <div className="editor-container">
        <ToolbarPlugin />
        <div className="editor-inner">
          <RichTextPlugin
            contentEditable={<ContentEditable className="editor-input" />}
            placeholder={<Placeholder />}
            ErrorBoundary={LexicalErrorBoundary}
          />
          {/* ADDED THIS: */}
          <EditorCapturePlugin ref={ref} />
          <HistoryPlugin />
          <AutoFocusPlugin />
          <CodeHighlightPlugin />
          <ListPlugin />
          <LinkPlugin />
          <AutoLinkPlugin />
          <ListMaxIndentLevelPlugin maxDepth={7} />
          <MarkdownShortcutPlugin transformers={TRANSFORMERS} />
        </div>
      </div>
    </LexicalComposer>
  );
});
Run Code Online (Sandbox Code Playgroud)