Javascript NextJS中的EditorJS无法加载插件

Javascript NextJS中的EditorJS无法加载插件,javascript,next.js,wysiwyg,server-side-rendering,editorjs,Javascript,Next.js,Wysiwyg,Server Side Rendering,Editorjs,我想在NextJS工作。编辑器在没有插件的情况下加载良好,只有段落作为块选项。但是,当我试图通过tools道具控制台添加插件时,会抛出以下警告: editor.js?9336:2 Module Tools was skipped because of TypeError: Cannot read property 'prepare' of undefined 当我在浏览器中单击编辑器时,它会抛出: Uncaught TypeError: Cannot read property 'holder

我想在NextJS工作。编辑器在没有插件的情况下加载良好,只有段落作为块选项。但是,当我试图通过tools道具控制台添加插件时,会抛出以下警告:

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导入componentdidmounthook中的编辑器和插件,但遇到了与NextJS动态导入相同的问题。尝试使用React ref获取组件,但发现当前尝试了建议的解决方法,但仍然没有结果。在触发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;
从“React”导入React;
从“下一个/动态”导入动态;
const EditorNoSSR=dynamic(()=>import(“react editor js”),{ssr:false});
const Embed=dynamic(()=>import(“@editorjs/Embed”),{ssr:false});
类编辑器扩展了React.Component{
状态={
编辑内容:{
区块:[
{
数据:{
文本:“测试文本”,
},
键入:“段落”,
},
],
},
};
建造师(道具){
超级(道具);
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(){
返回(
this.onEdit(api,newData)}
工具={{embed:embed}
ref={(el)=>{
this.editorRef=el;
}}
instanceRef={(实例)=>(this.editorInstance=instance)}
/>
);
}
}
导出默认编辑器;
这个问题有什么解决办法吗?我知道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>
     </>
   );
 }
}
类编辑器扩展React.Component{
建造师(道具){
超级(道具);
this.editor=null;
}
异步组件didmount(){
this.initEditor();
}
initEditor=()=>{
const EditorJS=require(“@EditorJS/EditorJS”);
const Header=require(“@editorjs/Header”);
const Embed=require(“@editorjs/Embed”);
常量分隔符=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”);
让content=null;
if(this.props.data!==未定义){
content=this.props.data;
}
this.editor=neweditorjs({
持有者:“editorjs”,
日志级别:“错误”,
工具:{
标题:标题,
嵌入:{
类别:嵌入,
配置:{
服务:{
youtube:没错,
库布:是的,
},
},
},
列表:列表,
inlineCode:inlineCode,
代码:代码,
表:表,,
quote:quote,
马克:马克,
检查表:检查表,
分隔符:分隔符,
},
数据:内容,
});
};
异步onSave(e){
让data=wait this.editor.saver.save();
此.props.save(数据);
}
render(){
返回(
这个.onSave(e)}>Save
此.onChange(e)}>
);
}
}
这个实现在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;
您可以使用您的组件:

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

来源:

我从来没有接触过next.js,而是使用nuxt.js。在nuxt.js中,如果您在客户端,可以使用
process.client
进行检查。您是否在next.js中使用了
if(process.browser){…}
我使用了条件if(typeof window!=='undefined'),只是为了确保它的行为符合要求,但这不会改变任何内容,因为它假定“根据我的理解”呈现仅将禁用ssr标志作为客户端进行动态导入。如果将
{ssr:false}
传递给动态导入选项,则不需要使用
if
语句。
return (
  {CustomEditor && <CustomEditor />}
)