我正在使用 React、Next.js 和 TipTap 作为项目的一部分。我最初一直将 TipTap 与
useEditor
一起使用,但为了提供更大的灵活性并防止需要将编辑器传递给编辑器中的每个子组件,我一直在重构以使用 <EditorProvider />
来代替。
使用
<EditorProvider>
时,代码似乎忽略 <EditorContent>
并将内容放置在 <EditorProvider />
子级的顶部。
我已将编辑器分成了自己的可重用组件
<BlockEditor>
,可以嵌套在 <EditorProvider />
中
BlockEditor.js
const BlockEditor = () => {
const { editor } = useCurrentEditor();
return (
<>
<FloatingMenu editor={null}>
<BlockMenu />
</FloatingMenu>
<BubbleMenu editor={null} className="flex space-x-2">
<TextMenu />
<ImageMenu />
<GalleryMenu />
</BubbleMenu>
<EditorContent editor={editor} />
</>
);
};
然后我在页面或其他客户端组件内使用
<BlockEditor>
,我想在其中控制布局,以便页面上的其他组件可以通过const { editor } = useCurrentEditor();
访问编辑器
ExampleEditor.js
export default function ExampleEditor() {
// define your extension array
const extensions = [
StarterKit
];
const content = `
<h1>
This is a test,
</h1>
`;
return (
<EditorProvider
extensions={extensions}
content={content}
>
<div className="w-full flex-1 flex overflow-hidden">
{/* Editor */}
<div className="h-full flex flex-col min-h-200 flex-grow overflow-hidden">
<div className="w-full p-4 overflow-hidden h-full">
<BlockEditor />
</div>
</div>
{/* Settings aside */}
<div className="h-full w-[350px] border-l border-neutral-200 bg-gray-50">
<TextInspector />
<ImageInspector />
<GalleryInspector />
</div>
</div>
</EditorProvider>
);
}
在此示例中
<TextInspector />
、<ImageInspector />
、<GalleryInspector />
都使用 useCurrentEditor();
来访问编辑器并为活动元素提供一些编辑实用程序。
问题在于 EditorProvider 似乎在其子级的顶部渲染内容,而不是在 BlockEditor.js
<EditorContent>
所在的位置。使用 useEditor
时这不是问题,但现在似乎成了问题。
关于
<EditorProvider>
的文档不多,所以我不确定它是否支持<EditorContent>
,以及我应该如何正确使用它。如果有任何关于我应该如何使用和嵌套 < EditorProvider>
和 <EditorContent>
的示例,那将是一个很大的帮助。
注意: 我注意到的另一个奇怪的事情是,偶尔在开发模式下运行 Next.js 应用程序并更新代码时,它会正确渲染一秒钟,然后再恢复到将内容放置在顶部提供者的孩子们。我认为这可能表明存在一些服务器端渲染问题;但是,所有编辑器组件都使用
"use client"
。
深入研究
node_modules
中的代码,了解EditorProvider
,它是这样定义的:
export function EditorProvider({
children, slotAfter, slotBefore, editorContainerProps = {}, ...editorOptions
}: EditorProviderProps) {
const editor = useEditor(editorOptions)
if (!editor) {
return null
}
return (
<EditorContext.Provider value={{ editor }}>
{slotBefore}
<EditorConsumer>
{({ editor: currentEditor }) => (
<EditorContent editor={currentEditor} {...editorContainerProps} />
)}
</EditorConsumer>
{children}
{slotAfter}
</EditorContext.Provider>
)
}
您可以使用
editorContainerProps
来设置EditorContent
相关的道具。您不需要单独使用EditorContent
。