NextJS 中的 EditorJS 无法加载插件



我正在尝试让EditorJS在NextJS中工作。编辑器在没有插件的情况下加载良好,将唯一的段落作为块选项。但是,当我尝试通过工具道具控制台添加插件时,会引发以下警告:

editor.js?9336:2 Module Tools was skipped because of TypeError: Cannot read property 'prepare' of undefined

当我在浏览器中单击编辑器时,它抛出:

Uncaught TypeError: Cannot read property 'holder' of undefined

我已经在普通的 React 应用程序中测试了编辑器插件,它们加载良好。这意味着问题出在 EditorJS 和 NextJS 导入和插件处理中。我尝试使用 require 在 componentDidMount 钩子中导入编辑器和插件,但遇到了与 NextJS 动态导入相同的问题。尝试使用 React ref 获取组件,但发现当前 NextJS 在获取组件的引用时存在问题,尝试了建议的解决方法,但仍然没有结果。在触发 onChange 之前,编辑器的实例不可用,因此由于 'prepare' 属性,插件无法挂接到编辑器,或者整个编辑器在编辑器上发生事件之前未定义,但编辑器输出到控制台它已准备就绪。

我的组件代码:

import React from "react";
import dynamic from "next/dynamic";
const EditorNoSSR = dynamic(() => import("react-editor-js"), { ssr: false });
const Embed = dynamic(() => import("@editorjs/embed"), { ssr: false });
class Editor extends React.Component {
state = {
editorContent: {
blocks: [
{
data: {
text: "Test text",
},
type: "paragraph",
},
],
},
};
constructor(props) {
super(props);
this.editorRef = React.createRef();
}
componentDidMount() {
console.log(this.editorRef.current);
console.log(this.editorInstance);
}
onEdit(api, newData) {
console.log(this.editorRef.current);
console.log(this.editorInstance);
this.setState({ editorContent: newData });
}
render() {
return (
<EditorNoSSR
data={this.state.editorContent}
onChange={(api, newData) => this.onEdit(api, newData)}
tools={{ embed: Embed }}
ref={(el) => {
this.editorRef = el;
}}
instanceRef={(instance) => (this.editorInstance = instance)}
/>
);
}
}
export default Editor;

这个问题有什么解决方案吗?我知道 SSR 在访问 DOM 的组件的客户端渲染方面具有挑战性,但是使用了检查窗口对象是否未定义的条件,但是,在我的情况下它看起来不是问题。

更新:

我已经找到了一个解决方案,但它不是解决问题的NextJS方法,但是,它有效。它不需要 react-editorjs,并且像普通的 EditorJS 一样作为 EditorJS 实例的创建实现。

class Editor extends React.Component {
constructor(props) {
super(props);
this.editor = null;
}
async componentDidMount() {
this.initEditor();
}
initEditor = () => {
const EditorJS = require("@editorjs/editorjs");
const Header = require("@editorjs/header");
const Embed = require("@editorjs/embed");
const Delimiter = require("@editorjs/delimiter");
const List = require("@editorjs/list");
const InlineCode = require("@editorjs/inline-code");
const Table = require("@editorjs/table");
const Quote = require("@editorjs/quote");
const Code = require("@editorjs/code");
const Marker = require("@editorjs/marker");
const Checklist = require("@editorjs/checklist");
let content = null;
if (this.props.data !== undefined) {
content = this.props.data;
}
this.editor = new EditorJS({
holder: "editorjs",
logLevel: "ERROR",
tools: {
header: Header,
embed: {
class: Embed,
config: {
services: {
youtube: true,
coub: true,
},
},
},
list: List,
inlineCode: InlineCode,
code: Code,
table: Table,
quote: Quote,
marker: Marker,
checkList: Checklist,
delimiter: Delimiter,
},
data: content,
});
};
async onSave(e) {
let data = await this.editor.saver.save();
this.props.save(data);
}
render() {
return (
<>
<button onClick={(e) => this.onSave(e)}>Save</button>
<div id={"editorjs"} onChange={(e) => this.onChange(e)}></div>
</>
);
}
}

此实现适用于 NextJS

如果我找到更好的解决方案,我将更新代码。

更新 2:

Rising Odegua建议的答案是有效的。

您必须创建一个单独的组件,然后在那里导入所有工具:

import EditorJs from "react-editor-js";
import Embed from "@editorjs/embed";
import Table from "@editorjs/table";
import List from "@editorjs/list";
import Warning from "@editorjs/warning";
import Code from "@editorjs/code";
import LinkTool from "@editorjs/link";
import Image from "@editorjs/image";
import Raw from "@editorjs/raw";
import Header from "@editorjs/header";
import Quote from "@editorjs/quote";
import Marker from "@editorjs/marker";
import CheckList from "@editorjs/checklist";
import Delimiter from "@editorjs/delimiter";
import InlineCode from "@editorjs/inline-code";
import SimpleImage from "@editorjs/simple-image";
const CustomEditor = () => {
const EDITOR_JS_TOOLS = {
embed: Embed,
table: Table,
marker: Marker,
list: List,
warning: Warning,
code: Code,
linkTool: LinkTool,
image: Image,
raw: Raw,
header: Header,
quote: Quote,
checklist: CheckList,
delimiter: Delimiter,
inlineCode: InlineCode,
simpleImage: SimpleImage
};
return (
<EditorJs tools={EDITOR_JS_TOOLS} />
);
}
export default CustomEditor;

然后在 NextJS 页面中,使用如下所示的动态导入:

let CustomEditor;
if (typeof window !== "undefined") {
CustomEditor = dynamic(() => import('../src/components/CustomEditor'));
}

您可以使用您的组件:

return (
{CustomEditor && <CustomEditor />}
)

来源 : https://github.com/Jungwoo-An/react-editor-js/issues/31

最新更新