Jungwoo-An / react-editor-js

⚛️📝The unofficial editor-js component for React
https://codesandbox.io/s/react-editor-js-v2-34bfl
MIT License
945 stars 78 forks source link

not working in next js correctly #31

Closed mramino closed 4 years ago

mramino commented 4 years ago

hi I imported this in Nextjs,dynamic because error for window but most plugin don't work

Jungwoo-An commented 4 years ago

@mramino Hi! First of all, thanks for your interest! ❤️

Unfortunately, editor-js does not support SSR. But, here is solution for you

Thanks!

Jungwoo-An commented 4 years ago

I close this issue. If you have anything more to say, plz reopen issue.

Thanks!

pauloamorimbr commented 3 years ago

@mramino Hi! First of all, thanks for your interest! ❤️

Unfortunately, editor-js does not support SSR. But, here is solution for you

Thanks!

Hi...I just want to add some stuff that made it work for me:

You need to create a full component with all the plugins you want to use and then dynamic import THAT component, and not dynamic import the EditorJs,or else you wont be able to add the plugins.

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";

function MyEditor() {

  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 MyEditor;

Also, you gonna get errors if you don't check for "window" existence like below:

//Remember to import the dynamic from Nextjs
import dynamic from 'next/dynamic';

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

...and then...

{MyEditor &&
    <MyEditor />
}

And thats how I got it to work! ;-)

ashu565 commented 3 years ago

It is showing that dynamic is not defined PLease help

pauloamorimbr commented 3 years ago

I updated my answer to include it. You just need to import "dynamic" form next:

//Remember to import the dynamic from Nextjs
import dynamic from 'next/dynamic';
sharu725 commented 2 years ago

I have followed the same method in NEXT 12, React 18, react-editor-js 2.0.6 but still get this error

Unhandled Runtime Error
Error: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.

Check the render method of `Editor`.

Here is my Editor component

import EditorJs from "react-editor-js";
import Embed from "@editorjs/embed";
import Table from "@editorjs/table";
import List from "@editorjs/list";

const Editor = () => {
  const EDITOR_JS_TOOLS = {
    embed: Embed,
    table: Table,
    list: List,
  };

  return (<EditorJs tools={EDITOR_JS_TOOLS} />);
}

export default Editor;

Here is the index.js

import dynamic from 'next/dynamic';
let Editor;

const CreateBlog = (props) => {
  if (typeof window !== "undefined") {
    Editor = dynamic(() => import('/components/Editor'));
  }
  const onSaveHandler = async (blogData, title, description) => {
    const toSaveData = {
      title,
      blogData,
      description,
    };

    console.log(toSaveData);
    //make your ajax call to send the data to your server and save it in a database
  };

  return (
    <div>
      {Editor && <Editor
        onSave={(blogData, title, description) =>
          onSaveHandler(blogData, title, description)
        }
      />}
    </div>
  );
};

export default CreateBlog;
oguzhanbahadir commented 2 years ago

I have followed the same method in NEXT 12, React 18, react-editor-js 2.0.6 but still get this error

Unhandled Runtime Error
Error: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.

Check the render method of `Editor`.

Here is my Editor component

import EditorJs from "react-editor-js";
import Embed from "@editorjs/embed";
import Table from "@editorjs/table";
import List from "@editorjs/list";

const Editor = () => {
  const EDITOR_JS_TOOLS = {
    embed: Embed,
    table: Table,
    list: List,
  };

  return (<EditorJs tools={EDITOR_JS_TOOLS} />);
}

export default Editor;

Here is the index.js

import dynamic from 'next/dynamic';
let Editor;

const CreateBlog = (props) => {
  if (typeof window !== "undefined") {
    Editor = dynamic(() => import('/components/Editor'));
  }
  const onSaveHandler = async (blogData, title, description) => {
    const toSaveData = {
      title,
      blogData,
      description,
    };

    console.log(toSaveData);
    //make your ajax call to send the data to your server and save it in a database
  };

  return (
    <div>
      {Editor && <Editor
        onSave={(blogData, title, description) =>
          onSaveHandler(blogData, title, description)
        }
      />}
    </div>
  );
};

export default CreateBlog;

same here, any solution?

z9fr commented 1 year ago

manage to find a solution

EditorTools.ts

import Header from "@editorjs/header";

export const EditorTools = {
  header: {
    class: Header,
    config: {
      placeholder: "Let`s write an awesome story! ✨",
    },
  },
};

export const i18n = {
  messages: {},
};

Editor.ts

import { useEffect, useRef, useState } from "react";

import EditorJS, { API, OutputData } from "@editorjs/editorjs";
import useId from "@mui/utils/useId";

import { EditorTools, i18n } from "./EditorTools";

type ArticleEditorProps = {
  defaultValue: OutputData;
  placeholder?: string;
  readOnly?: boolean;
  minHeight?: number;
  onReady: () => void;
  onSave: (data: OutputData) => void;
  onChange: (api: API, event: CustomEvent) => void;
};

const ArticleEditor = ({
  defaultValue,
  placeholder,
  readOnly,
  minHeight,
  onReady,
  onChange,
  onSave,
}: ArticleEditorProps) => {
  const id = useId();
  const editorJS = useRef<EditorJS | null>(null);
  const [currentArticle, setCurrentArticle] = useState<OutputData | null>(null);
  useEffect(() => {
    if (editorJS.current === null) {
      editorJS.current = new EditorJS({
        placeholder,
        readOnly,
        minHeight,
        holder: id,
        data: defaultValue,
        i18n,
        tools: EditorTools,
        onChange(api: API, event: CustomEvent) {
          editorJS.current?.save().then((res) => {
            setCurrentArticle(res);
            onSave(res);
          });
          onChange(api, event);
        },
        onReady() {
          onReady();
        },
      });
    }
  });
  return <div id={id} />;
};

ArticleEditor.defaultProps = {
  placeholder: "Let's write an awesome story! ✨",
  readOnly: false,
  minHeight: 0,
};

export default ArticleEditor;

using the Article Editor

import { useState } from "react";
import dynamic from "next/dynamic";
import { Suspense } from "react";

const ArticleEditor = dynamic(() => import("../../components/Editor/Editor"), {
  ssr: false,
});

const CreateEventPage = () => {
  const theme = useTheme();
  const data = {};

  return (
    <>
      <Suspense fallback={`Loading...`}>
        <ArticleEditor
          defaultValue={{
            time: 1635603431943,
            blocks: [],
          }}
          onChange={(api, event) => console.log("sample")}
          onReady={() => console.log("ready")}
          onSave={(d: any) => {
            console.log("SAVED");
            console.log(d);
          }}
        />
      </Suspense>
    </>
  );
};

export default CreateEventPage;
pawandeore commented 1 year ago

not working

pawandeore commented 1 year ago

does anyone have JS only solution i don't know typescript

thinkdj commented 1 year ago

I have followed the same method in NEXT 12, React 18, react-editor-js 2.0.6 but still get this error

Unhandled Runtime Error
Error: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.

Check the render method of `Editor`.

Facing the same issue. Tried multiple fixes, none worked.

TS lint says TS2604: JSX element type 'EditorJs' does not have any construct or call signatures.