Home / Blog / How to integrate Editor JS in NextJs(App Router) and ReactJs

How to integrate Editor JS in NextJs(App Router) and ReactJs

4 min read.Apr 16, 2024

How to integrate Editor JS in NextJs(App Router) and ReactJs

A guide to integrate editorJs in NextJs and React. Adding multiple editorjs tools like heading, Hyperlink image etc.

Table of Content

InstallationConfigurations for EditorJsBuilding up a reusable Editor ComponentHow to use it on ReactHow to use it on NextJs App RouterSource Code

Lets begin the journey to implement EditorJs.

Installation

Install Editor Js

npm i @editorjs/editorjs

install different tools of editorJs

npm i @editorjs/checklist @editorjs/code @editorjs/embed @editorjs/header @editorjs/image @editorjs/inline-code @editorjs/list @editorjs/paragraph @editorjs/quote editorjs-hyperlink

Configurations for EditorJS

Intialize a React and NextJs project

npx create-react-app editorjs-react

npx create-next-app editorjs-nextjs

creating an editor js config file

//editorjs.config.js

import CheckList from "@editorjs/checklist";
import Code from "@editorjs/code";
import Embed from "@editorjs/embed";
import InlineCode from "@editorjs/inline-code";
import Hyperlink from "editorjs-hyperlink";
import List from "@editorjs/list";
import Quote from "@editorjs/quote";
import Paragraph from "@editorjs/paragraph";
import Header from "@editorjs/header";
import Image from '@editorjs/image';

const EDITOR_CONFIG = {

    code: Code,

    header: {
        class: Header,
        config: {
            placeholder: 'Enter a Heading',
            levels: [2, 3, 6], //configure heading tags (e.g. h1,h2,h3 etc) to be shown in editorjs component
            defaultLevel: 2
        }
    },

    hyperlink: {
        class: Hyperlink,
        config: {
            shortcut: 'CMD+L',
            target: '_blank',
            rel: 'nofollow',
            availableTargets: ['_blank', '_self'],
            availableRels: ['author', 'noreferrer'],
            validate: false,
        }
    },

    paragraph: {
        class: Paragraph,
        inlineToolbar: true
    },

    image: {
        class: Image,
        config: {
            uploader: {
                uploadByFile: (file) => { //this function will be triggered when image gets selected
                    return {
                        success: 1,
                        file: {
                            // i'm creating a blob from the image file you can do your api call to upload the image somewhere and store the actual url
                            url: URL.createObjectURL(file),
                            raw: file
                        }
                    }
                }
            }
        }

    },

    checklist: CheckList,

    embed: Embed,

    inlineCode: InlineCode,

    list: {
        class: List,
        inlineToolbar: true
    },

    quote: Quote
}

export { EDITOR_CONFIG }

Building up an Reusable Editor Component

//Editor.jsx

'use client';
import EditorJS from "@editorjs/editorjs";
import classes from '../styles/editorjs.module.css';
import { useEffect, useRef } from "react";
import { EDITOR_CONFIG } from "../configs/editorjs.config";

const Editor = ({ value, onChange, holder }) => {

    const ref = useRef();

    useEffect(() => {

        if (!ref.current) {
            const editor = new EditorJS({
                holder: holder,
                tools: EDITOR_CONFIG,
                placeholder: 'Write an Amazing Blog',
                data: value,
                async onChange(api, event) {
                    const data = await api.saver.save();
                    onChange(data);
                },
                i18n: {
                    toolNames: {
                        Hyperlink: 'Link'
                    },
                    tools: {
                        hyperlink: {
                            Save: 'Salvar',
                            'Select target': 'Seleziona destinazione',
                            'Select rel': 'Wählen rel'
                        }
                    }
                }
            })

            ref.current = editor;
        }

        return () => {
            if (ref.current && ref.current.destroy) {
                ref.current.destroy();
            }
        };
    }, []);


    return (
        <div id={holder} className={classes.editorjs} py={4} border={'1px solid rgb(190, 195, 224, 0.4)'} borderRadius={6} />
    )
}


export default Editor;

How to use it on React

// App.jsx

import { useState } from 'react'
import Editor from './components/Editor'

const App = () => {

  const [data, setData] = useState('');

  return (
    <div>
      <Editor value={data} onChange={setData} holder="editorjs-container" />
    </div>
  )
}

export default App

How to use it on NextJs App Router

'use client';
import dynamic from "next/dynamic";
import { useState } from "react";

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

const page = () => {

  const [data, setData] = useState('');

  return (
    <div>
      <Editor value={data} onChange={setData} holder="editorjs-container" />
    </div>
  )
}

export default page;

Source Code

check here