Open In App

Create a Markdown Editor using React Hooks and CodeMirror

Last Updated : 27 Mar, 2024
Improve
Improve
Like Article
Like
Save
Share
Report

Creating a Markdown Editor with React Hooks and CodeMirror is a great way to build a simple yet powerful text editing tool. CodeMirror is a versatile text editor component that can be easily integrated into React applications. Here’s a basic example of how you can create a Markdown editor using React Hooks and CodeMirror:

Output Preview: Let us have a look at how the final output will look like.

Screenshot-2024-03-20-224640

Prerequisites:

Approach to create a Markdown Editor:

  • The MarkdownEditor component is a React component used for editing and previewing Markdown content.
  • It utilizes the CodeMirror library for the text editor portion.
  • State is managed using the useState hook, with markdown content stored in the state.
  • The width of the text editor and preview sections is adjustable via a resizer element.
  • Event listeners are used to track mouse movements for resizing.
  • The marked library is employed to render Markdown content as HTML for the preview section.
  • The App component imports and renders the MarkdownEditor component within its structure.
  • Overall, the MarkdownEditor provides a user-friendly interface for editing and previewing Markdown content.

Steps to Create a React App and Installing Module:

Step 1: Create a new React application using Create React App:

npx create-react-app editor

Step 2: Navigate to the project directory:

cd editor

Step 3: Install CodeMirror and its dependencies using npm:

npm install codemirror react-codemirror2 marked

If you encountered a dependency resolution issue:

npm install codemirror react-codemirror2 --force
npm install marked --force

OR

npm install codemirror react-codemirror2 --legacy-peer-deps
npm install marked --legacy-peer-deps

Project Structure:

Screenshot-2024-03-20-224220

The Updated dependencies in package.json file will look like:

"dependencies": {
"@testing-library/jest-dom": "^5.17.0",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^13.5.0",
"codemirror": "^5.65.16",
"marked": "^12.0.1",
"react": "^18.2.0",
"react-codemirror2": "^7.3.0",
"react-dom": "^18.2.0",
"react-scripts": "5.0.1",
"web-vitals": "^2.1.4"
},

Step 4: Create the necessary files

  • Insider src folder create MarkdownEditor.js files
  • Replace the code of index.js , App.js and App.css with the given code below

Example: Below is an example of Creating a Markdown Editor with React Hooks and CodeMirror.

CSS
/* App.css */
.App {
    font-family: Arial, sans-serif;
    text-align: center;
    padding: 20px;
}

header {
    background-color: #333;
    color: #fff;
    padding: 20px 0;
}

header h1 {
    margin: 0;
}

.main-container {
    background-color: #f6f1f1;
    display: flex;
    justify-content: center;
    align-items: flex-start;
    margin-top: 20px;
    border: 2px solid black;
}

.text-editor {
    flex: 1;
    min-width: 0;
    /* Allow text editor to shrink beyond its content width */
}

.preview {
    /* background-color: #ccc; */
    flex: 1;
    min-width: 0;
    /* Allow preview to shrink beyond its content width */
    margin-left: 20px;
    /* Add space between text editor and preview */
}

.CodeMirror {
    height: 300px;
    border: 1px solid #ccc;
}

@media screen and (max-width: 768px) {
    .main-container {
        flex-direction: column;
        align-items: center;
    }

    .preview {
        margin-left: 0;
        margin-top: 20px;
        /* Add space between text editor and preview in mobile view */
    }
}
JavaScript
// MarkdownEditor.js
import React, {
    useState
} from 'react';
import {
    Controlled as CodeMirror
} from 'react-codemirror2';
import 'codemirror/lib/codemirror.css';
import 'codemirror/theme/material.css';
import 'codemirror/mode/markdown/markdown';
import {
    marked
} from 'marked';

const MarkdownEditor = () => {
    const [markdown, setMarkdown] = useState('');
    const [editorWidth, setEditorWidth] = useState('50%');

    const handleChange = (editor, data, value) => {
        setMarkdown(value);
    };

    const handleMouseMove = (e) => {
        setEditorWidth(`
        ${100 * (e.clientX / window.innerWidth)}%`);
    };

    const handleMouseUp = () => {
        document.removeEventListener('mousemove',
            handleMouseMove);
        document.removeEventListener('mouseup',
            handleMouseUp);
    };

    const handleMouseDown = () => {
        document.addEventListener('mousemove',
            handleMouseMove);
        document.addEventListener('mouseup',
            handleMouseUp);
    };

    return (
        <div className="markdown-editor">
            <div className="main-container">
                <div className="text-editor" style={{
                    width: editorWidth
                }}>
                    <CodeMirror
                        value={markdown}
                        onBeforeChange={handleChange}
                        options={{
                            mode: 'markdown',
                            theme: 'material',
                            lineNumbers: true
                        }}
                    />
                </div>
                <div
                    className="resizer"
                    onMouseDown={handleMouseDown}
                ></div>
                <div className="preview" style={{
                    width: `calc(100% - ${editorWidth})`
                }}>
                    <h2>Preview</h2>
                    <div dangerouslySetInnerHTML={{
                        __html: marked(markdown)
                    }} />
                </div>
            </div>
        </div>
    );
};

export default MarkdownEditor;
JavaScript
// App.js
import React from 'react';
import MarkdownEditor from './MarkdownEditor.js';
import './App.css';

function App() {
    return (
        <div className="App">
            <header className="App-header">
                <h1>Markdown Editor</h1>
            </header>
            <main>
                <MarkdownEditor />
            </main>
        </div>
    );
}

export default App;
JavaScript
//index.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  
    <App />
  
);

Start your application using the following command:

npm start

Output:

ee



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads