Build a Simple React JS Interactive Web-Based Markdown Previewer: A Beginner’s Guide

In the world of web development, the ability to format text using Markdown is a valuable skill. Markdown allows you to write content in a simple, easy-to-read format, which can then be converted into HTML. This is particularly useful for blogging, documentation, and any scenario where you need to present text in a clean and organized manner. But what if you could see how your Markdown text would look in real-time? That’s where a Markdown previewer comes in. This tutorial will guide you through building a simple, interactive Markdown previewer using React JS. We’ll break down the process step-by-step, making it easy for beginners to understand and implement.

Why Build a Markdown Previewer?

Creating a Markdown previewer is an excellent project for several reasons:

  • Practical Application: It solves a real-world problem by allowing users to instantly see the rendered output of their Markdown text.
  • Learning Opportunity: It provides hands-on experience with fundamental React concepts such as state management, event handling, and component composition.
  • Skill Enhancement: It helps you understand how to integrate third-party libraries (in this case, a Markdown parser) into your React applications.

This project is perfect for beginners because it’s focused, achievable, and allows you to build something functional and useful relatively quickly.

What You’ll Need

Before we dive into the code, let’s make sure you have the necessary tools and knowledge:

  • Basic Understanding of HTML, CSS, and JavaScript: You should be familiar with the basics of these web technologies.
  • Node.js and npm (or yarn) installed: These are required to manage project dependencies and run the development server.
  • A Code Editor: Such as Visual Studio Code, Sublime Text, or Atom.
  • A Web Browser: Chrome, Firefox, Safari, or any modern browser.

Setting Up the React Project

Let’s start by creating a new React project using Create React App. This is the easiest way to get a React project up and running quickly. Open your terminal or command prompt and run the following command:

npx create-react-app markdown-previewer
cd markdown-previewer

This command creates a new directory called markdown-previewer, sets up a basic React application, and navigates you into the project directory. Next, start the development server:

npm start

This will open your React application in your default web browser, usually at http://localhost:3000. Now, let’s clean up the default files to prepare for our Markdown previewer.

Cleaning Up the Boilerplate

Navigate to the src directory within your project and delete the following files:

  • App.css
  • App.test.js
  • index.css
  • logo.svg
  • reportWebVitals.js
  • setupTests.js

Next, open App.js and replace its contents with the following basic structure:

import React, { useState } from 'react';

function App() {
  return (
    <div className="container">
      <h1>Markdown Previewer</h1>
      <textarea></textarea>
      <div></div>
    </div>
  );
}

export default App;

This provides a basic structure with a heading, a textarea for Markdown input, and a div to display the rendered HTML. We’ll add styling and functionality in the following steps.

Installing the Markdown Parser

We’ll use a library called marked to parse the Markdown text into HTML. Install it using npm or yarn:

npm install marked

Or, if you are using yarn:

yarn add marked

Import marked into your App.js file:

import React, { useState } from 'react';
import { marked } from 'marked';

Adding State for Markdown Input

We need a way to store the Markdown text entered by the user. We’ll use React’s useState hook for this. Add the following line inside the App component, right after the function App() { line:

const [markdown, setMarkdown] = useState('');

This creates a state variable called markdown and a function setMarkdown to update its value. The initial value is set to an empty string.

Handling User Input

We need to update the markdown state whenever the user types in the textarea. Add an onChange event handler to the textarea:

<textarea
  onChange={(e) => setMarkdown(e.target.value)}
></textarea>

This code does the following:

  • onChange: This event fires every time the value of the textarea changes.
  • (e) => setMarkdown(e.target.value): This is an arrow function. It takes the event object (e) as an argument and calls the setMarkdown function, updating the markdown state with the value of the textarea (e.target.value).

Rendering the Markdown

Now, let’s render the Markdown text as HTML. Inside the App component, before the return statement, add the following code:

const html = marked(markdown);

This line calls the marked function, passing the markdown state as an argument, and assigns the resulting HTML to the html variable. Now, in the div where we want to display the preview, we need to render the HTML. Replace the empty <div></div> with the following:

<div dangerouslySetInnerHTML={{ __html: html }}></div>

Important: Because we’re rendering HTML that comes from user input, we need to use dangerouslySetInnerHTML. This is a React prop that allows you to inject raw HTML. Note that this can be a security risk if you’re not careful about sanitizing the input. In our case, the marked library handles the sanitization for us.

Adding Basic Styling

Create a file named App.css in the src directory and add the following CSS rules. This will give our previewer a basic, clean look:

.container {
  width: 80%;
  margin: 20px auto;
  display: flex;
  flex-direction: column;
}

textarea {
  width: 100%;
  height: 200px;
  padding: 10px;
  margin-bottom: 10px;
  font-family: monospace;
  font-size: 16px;
  border: 1px solid #ccc;
  border-radius: 4px;
}

div[dangerouslySetInnerHTML] {
  width: 100%;
  padding: 10px;
  border: 1px solid #ccc;
  border-radius: 4px;
  background-color: #f9f9f9;
  overflow: auto; /* For long content */
}

@media (min-width: 768px) {
  .container {
    flex-direction: row;
    justify-content: space-between;
  }

  textarea {
    width: 48%;
  }

  div[dangerouslySetInnerHTML] {
    width: 48%;
  }
}

Import the CSS file into App.js by adding the following line at the top of the file:

import './App.css';

This CSS provides a responsive layout, with the input and preview side-by-side on larger screens and stacked on smaller screens.

Complete Code (App.js)

Here’s the complete code for App.js:

import React, { useState } from 'react';
import { marked } from 'marked';
import './App.css';

function App() {
  const [markdown, setMarkdown] = useState('');
  const html = marked(markdown);

  return (
    <div className="container">
      <h1>Markdown Previewer</h1>
      <textarea
        onChange={(e) => setMarkdown(e.target.value)}
        value={markdown}
      ></textarea>
      <div dangerouslySetInnerHTML={{ __html: html }}></div>
    </div>
  );
}

export default App;

Testing Your Markdown Previewer

Save all the files and go back to your browser. You should now see the Markdown previewer in action. Try typing some Markdown in the textarea. As you type, the rendered HTML should appear in the preview area below.

Here are some examples of Markdown you can try:

  • Headings: # Heading 1, ## Heading 2, ### Heading 3
  • Bold and Italic: **bold text**, *italic text*
  • Lists: - item 1, - item 2
  • Links: [link text](https://www.example.com)
  • Code blocks: ```javascript
    console.log('Hello, world!');
    ```

Common Mistakes and How to Fix Them

Here are some common mistakes and how to avoid them:

  • Not installing marked: Make sure you run npm install marked (or yarn) to install the Markdown parser.
  • Incorrectly importing marked: Double-check that you’re importing marked correctly: import { marked } from 'marked';.
  • Forgetting the onChange handler: The onChange event handler is crucial for updating the state when the user types in the textarea. Make sure it’s correctly implemented.
  • Using innerHTML instead of dangerouslySetInnerHTML: Because we are rendering HTML generated from user input, you must use dangerouslySetInnerHTML.
  • CSS Issues: If your layout looks off, carefully check your CSS. Ensure that the CSS is correctly applied, the class names match, and there are no conflicting styles. Use your browser’s developer tools to inspect the elements and debug any CSS issues.

Advanced Features (Optional)

Here are some ideas to extend the functionality of your Markdown previewer:

  • Toolbar: Add a toolbar with buttons to insert Markdown syntax (e.g., bold, italic, headings).
  • Live Preview Options: Allow the user to toggle between live preview and editing mode.
  • Syntax Highlighting: Use a library like highlight.js to add syntax highlighting to code blocks.
  • Markdown Editor: Integrate a full-fledged Markdown editor component for a richer editing experience.
  • Saving and Loading: Implement functionality to save and load Markdown content from local storage or a server.

Key Takeaways

In this tutorial, you’ve learned how to build a simple but effective Markdown previewer using React. You’ve gained practical experience with:

  • Setting up a React project.
  • Using the useState hook to manage component state.
  • Handling user input with onChange events.
  • Integrating a third-party library (marked).
  • Rendering HTML with dangerouslySetInnerHTML.
  • Adding basic styling.

FAQ

  1. Why use a Markdown previewer? A Markdown previewer allows you to see the rendered output of your Markdown text in real-time, making it easier to format your content and ensure it looks the way you want it to.
  2. What is marked? marked is a JavaScript library that parses Markdown text and converts it into HTML.
  3. Why do we use dangerouslySetInnerHTML? We use dangerouslySetInnerHTML because we are rendering HTML generated from user input. This prop allows us to inject raw HTML into the DOM. It’s important to be aware of the security implications.
  4. Can I use this previewer in my own projects? Absolutely! This is a fully functional component you can adapt and integrate into your own React projects.
  5. How can I improve the styling? You can customize the CSS to match the look and feel of your application. Consider using a CSS framework such as Bootstrap or Tailwind CSS for more advanced styling.

By building this Markdown previewer, you’ve taken a significant step forward in your React learning journey. You now have a practical, reusable component and a solid understanding of fundamental React concepts. Continue experimenting, exploring, and building! As you delve deeper into React, you’ll find that the possibilities are endless. Keep practicing, and don’t be afraid to experiment with new features and libraries. The more you build, the more confident you’ll become. Your ability to create dynamic, interactive web applications will grow with each project you undertake, and the skills you’ve acquired here will serve as a strong foundation for your future endeavors. Embrace the journey, and enjoy the process of learning and creating.