Create a Markdown Editor using React Hooks and CodeMirror
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.
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:
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.
/* 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 */
}
}
// 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;
// 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;
//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:
Contact Us