DEV Community

Cover image for Integrate an open source (🆓) Rich Text Editor Component (Wyswig) in your React app 👨‍💻
Zhitomir Oreshenski
Zhitomir Oreshenski

Posted on • Edited on

Integrate an open source (🆓) Rich Text Editor Component (Wyswig) in your React app 👨‍💻

Table of Contents

  • Create a simple react app
  • Create a simple architecture
  • Install all necessary dependencies
  • Create and configure the Editor component
  • Use it

Create a simple react app

npx create-react-app wyswig-editor --typescript
cd wyswig-editor
yarn start

Enter fullscreen mode Exit fullscreen mode

Create a simple architecture

-> In the terminal execute following:

cd src && mkdir components editor

Enter fullscreen mode Exit fullscreen mode

Install all necessary dependencies


-> Using Yarn:

 yarn add react-draft-wysiwyg draft-js draftjs-to-html @types/react-draft-wysiwyg @types/draftjs @types/draft-to-html

-> Using Npm:

npm install react-draft-wysiwyg draft-js draftjs-to-html @types/react-draft-wysiwyg @types/draftjs @types/draft-to-html

-> Without Typescript only:

yarn add react-draft-wysiwyg draft-js draftjs-to-html

Enter fullscreen mode Exit fullscreen mode

Create and configure the Editor component


-> src/components/WysiwygEditor.tsx

import React, { Fragment, useCallback } from 'react';
import { Editor as ReactWysiwygEditor } from 'react-draft-wysiwyg';
import { useEditor, useEditorConfig } from '../../editor';

export const WysiwygEditor = () => {
  const { editorOptions } = useEditorConfig();
  const {
    editorState,
    setEditorState,
    enteredText,
    setEnteredText,
    convertedHtml,
    getEditorText,
  } = useEditor();

  const handleEditorStateChange = useCallback(
    (editorState) => {
      const text = getEditorText(editorState.getCurrentContent());
      setEditorState(editorState);
      setEnteredText(text);
    },
    [getEditorText, setEditorState, setEnteredText]
  );

  return (
    <Fragment>
      <ReactWysiwygEditor
        editorState={editorState}
        onEditorStateChange={handleEditorStateChange}
        placeholder="Type here..."
        toolbar={editorOptions}
      />
      <textarea
        className="textarea"
        disabled
        value={editorState && convertedHtml}
      />
      <div>Editor text: {enteredText}</div>
    </Fragment>
  );
};

-> src/utils/helpers/constants.ts

export const DEFAULT_IMAGE_SIZE = {
  height: '500',
  width: '500',
};

export const EDITOR_OPTIONS = [
  'inline',
  'blockType',
  'list',
  'textAlign',
  'history',
  'image',
];

-> src/utils/helpers/index.ts

export * from './constants';

-> src/editor/hooks/index.ts

export * from './useEditor';
export * from './useEditorConfig';

-> src/editor/hooks/useEditor.ts

import { ContentState, convertToRaw, EditorState } from 'draft-js';
import draftToHtml from 'draftjs-to-html';
import { useCallback, useState } from 'react';

export const useEditor = () => {
  const [editorState, setEditorState] = useState<EditorState>(
    EditorState.createEmpty() || null
  );
  const [enteredText, setEnteredText] = useState<string>('');
  const [uploadImages, setUploadImages] = useState<any>([]);

  const getEditorText = useCallback(
    (raw: ContentState) => raw.getPlainText(),
    []
  );

  const rawData = convertToRaw(editorState.getCurrentContent());
  const convertedHtml = draftToHtml(rawData);

  return {
    enteredText,
    setEnteredText,
    editorState,
    setEditorState,
    convertedHtml,
    rawData,
    getEditorText,
  };
};


-> src/editor/hooks/useEditorConfig.ts

import { useCallback } from 'react';
import { DEFAULT_IMAGE_SIZE, EDITOR_OPTIONS } from '../../utils';

export const useEditorConfig = () => {
  const makeEditorOptions = useCallback(() => {
    return {
      options: EDITOR_OPTIONS,
      image: {
        alt: { present: true, mandatory: true },
        defaultSize: DEFAULT_IMAGE_SIZE,
      },
      blockType: { inDropdown: true },
      inline: { inDropdown: false },
      list: { inDropdown: false },
      textAlign: { inDropdown: false },
      link: { inDropdown: false },
      history: { inDropdown: false },
    };
  }, []);

  const editorOptions = makeEditorOptions();

  return { editorOptions };
};

Enter fullscreen mode Exit fullscreen mode

Use it


-> App.tsx

import React from 'react';
import { WysiwygEditor } from './components';

import './App.css';

const App = () => {
  return (
    <>
      <WysiwygEditor />
    </>
  );
}

export default App;

-> App.css

.App {
  margin-left: 20px;
}

.textarea {
  width: 35vw;
  height: 20vh;
}

Enter fullscreen mode Exit fullscreen mode

Now you can see the result:

Alt Text

Useful links:
React official docs
React Wysiwyg Editor


Thank you for reading this article! I hope you find it useful🚀

Top comments (0)