【发布时间】:2021-02-26 10:54:38
【问题描述】:
我正在使用 React 制作一个小型 CMS 系统,并且我有一个表单,用户可以在其中使用 Draft.js 编辑器以及其他一些字段。对于心中的问题,让我们专注于编辑表单。
编辑器的代码如下所示:
import React, { useRef } from 'react';
import { Formik } from "formik";
import TextInputField from "@/components/TextInputField";
import client from "@/utils/http";
const MyForm = ({title, content}) => {
const editorRef = useRef();
function handleSubmit(values) {
const editorContent = editorRef.current.parse();
client.submit('/api/edit/project', { editorContent, ...values });
}
return (
<Formik onSubmit={formik.handleSubmit} initialValues={{ title }}>
{
(formik) => (
<form onSubmit={formik.handleSubmit}>
<TextInputField label="title" name="title" />
<RichEditor ref={editorRef} content={content} />
</form>
)}
</Formik>);
}
我有编辑器代码:
import React, { useImperativeHandle, useState } from "react";
import {
Editor,
EditorState,
convertFromHTML,
ContentState,
convertToRaw,
} from "draft-js";
import draftToHtml from "draftjs-to-html";
function createFromContent(htmlContent) {
const blocksFromHtml = convertFromHTML(htmlContent);
const editorState = ContentState.createFromBlockArray(
blocksFromHtml.contentBlocks,
blocksFromHtml.entityMap
);
return EditorState.createWithContent(editorState);
}
function formatToHTML(editorState) {
const raw = convertToRaw(editorState.getCurrentContent());
const markup = draftToHtml(raw);
return markup;
}
function RichEditor({ content = null }, ref) {
const [editorState, setEditorState] = useState(() =>
content ? createFromContent(content) : EditorState.createEmpty()
);
useImperativeHandle(
ref,
() => ({
parse: () => {
return formatToHTML(editorState);
},
}),
[editorState]
);
return (
<div className="App-Rich-Editor w-full block border border-gray-300 rounded-md mt-4 shadow-sm">
<Editor
placeholder="Enter your content..."
editorState={editorState}
onChange={setEditorState}
/>
</div>
);
}
export default React.forwardRef(RichEditor);
这有效,但它让我想到了以下问题,因此为什么要问社区,因为使用 useImperativeHandle 似乎是“黑客”。因为即使是 React 文档也不鼓励使用它。
与往常一样,在大多数情况下应避免使用 refs 的命令式代码。
因为我想格式化编辑器的内部状态只格式化一次,所以当我提交表单时,我显示的代码是否合理,即使它“逆流而上”,通过使用命令句柄与父共享子状态。
这让我想到了问题:
- 在这种情况下是否可以使用
useImperativeHandle挂钩,以进行“优化”,以便我们仅在需要时才获取状态? - 是否有更好的方法可以使用“常规”模式(例如“提升状态”、“渲染道具”或其他方式)来实现此实现?
- 我是否忽略了这里的问题,我是否应该硬着头皮将整个编辑器状态与
formik同步,将其从组件中抬起,然后在提交时对其进行格式化?
对我来说,第三种选择似乎打破了关注点的分离,因为它会用状态逻辑污染Form 上下文,感觉它不属于那里。
【问题讨论】:
标签: reactjs react-hooks formik draftjs