Build a React JS Interactive Simple Interactive Component: A Basic Interactive Markdown Previewer with Dynamic Updates

In the digital age, content creation and sharing are at an all-time high. Writers, bloggers, and developers often need a simple and effective way to format their text for the web. Markdown, a lightweight markup language, has become a popular choice for its readability and ease of use. However, manually converting Markdown to HTML can be tedious. This tutorial will guide you through building a React JS interactive Markdown previewer component, enabling users to write Markdown and instantly see the rendered HTML output. This project not only demonstrates the power of React but also introduces fundamental concepts such as state management, event handling, and component composition.

Why Build a Markdown Previewer?

A Markdown previewer is more than just a code exercise; it’s a practical tool. Imagine you’re writing a blog post. Instead of switching between a Markdown editor and a separate preview window, you can see the formatted output in real-time. This immediate feedback loop enhances the writing experience, reduces errors, and saves time. Furthermore, building this component provides a solid understanding of how React handles user input and dynamically updates the user interface (UI).

Prerequisites

Before we dive in, ensure you have the following:

  • Node.js and npm (or yarn) installed on your system.
  • A basic understanding of HTML, CSS, and JavaScript.
  • A code editor (like VS Code, Sublime Text, or Atom).

Setting Up the React Project

Let’s start by creating a new React application using Create React App. Open your terminal and run the following command:

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

This command sets up a new React project with all the necessary dependencies. Navigate into the project directory using `cd markdown-previewer`.

Installing the Markdown Parser

To convert Markdown to HTML, we’ll use a Markdown parser library. There are several options available; for this tutorial, we will use `marked`. Install it using npm or yarn:

npm install marked

or

yarn add marked

The `marked` library will handle the heavy lifting of parsing the Markdown text.

Building the Markdown Previewer Component

Now, let’s create the core component. Open `src/App.js` and replace the existing content with the following code:

import React, { useState } from 'react';
import { marked } from 'marked';
import './App.css'; // Import your CSS file

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

  const handleChange = (event) => {
    setMarkdown(event.target.value);
  };

  const html = marked.parse(markdown);

  return (
    <div className="container">
      <div className="editor-container">
        <h2>Editor</h2>
        <textarea
          id="editor"
          className="editor"
          value={markdown}
          onChange={handleChange}
        />
      </div>
      <div className="preview-container">
        <h2>Preview</h2>
        <div
          id="preview"
          className="preview"
          dangerouslySetInnerHTML={{ __html: html }}
        />
      </div>
    </div>
  );
}

export default App;

Let’s break down this code:

  • We import `useState` from React to manage the component’s state and `marked` to parse Markdown.
  • We define a state variable `markdown` using `useState`, initialized as an empty string. This variable will hold the Markdown text entered by the user.
  • The `handleChange` function updates the `markdown` state whenever the user types in the textarea.
  • `marked.parse(markdown)` converts the Markdown text to HTML.
  • The component renders a `textarea` for the user to input Markdown and a `div` to display the rendered HTML.
  • `dangerouslySetInnerHTML` is used to inject the HTML generated by `marked` into the `preview` div. This is necessary because React normally escapes HTML to prevent cross-site scripting (XSS) attacks. In this case, we know the source of the HTML (the `marked` library) and can safely render it.

Styling the Component

To make the previewer visually appealing, let’s add some basic CSS. Create a file named `src/App.css` and add the following styles:

.container {
  display: flex;
  flex-direction: row;
  width: 100%;
  height: 100vh;
  padding: 20px;
  box-sizing: border-box;
}

.editor-container, .preview-container {
  flex: 1;
  padding: 10px;
  border: 1px solid #ccc;
  margin: 10px;
  border-radius: 5px;
  box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
}

.editor {
  width: 100%;
  height: 80%;
  padding: 10px;
  font-family: monospace;
  font-size: 14px;
  border: 1px solid #ddd;
  border-radius: 4px;
  resize: vertical;
}

.preview {
  width: 100%;
  height: 80%;
  padding: 10px;
  font-family: sans-serif;
  font-size: 14px;
  border: 1px solid #ddd;
  border-radius: 4px;
  overflow-y: auto; /* Add scroll if content overflows */
  background-color: #f9f9f9;
  color: #333;
}

/* Optional: Basic Markdown styling */
.preview h1, .preview h2, .preview h3, .preview h4, .preview h5, .preview h6 {
  margin-top: 1em;
  margin-bottom: 0.5em;
}

.preview p {
  margin-bottom: 1em;
}

.preview a {
  color: blue;
  text-decoration: none;
}

.preview a:hover {
  text-decoration: underline;
}

.preview strong {
  font-weight: bold;
}

.preview em {
  font-style: italic;
}

These styles create a basic layout for the editor and preview areas and add some basic Markdown styling for headings, paragraphs, links, and emphasis. Adjust the styles to your liking.

Running the Application

Save the changes and start the development server by running the following command in your terminal:

npm start

or

yarn start

This will open your application in a new browser tab (usually at `http://localhost:3000`). Now, as you type Markdown in the left-hand editor, the right-hand preview will dynamically update with the rendered HTML.

Adding Features: Making the Preview Dynamic

The core functionality is complete, but let’s enhance the previewer with dynamic updates. The `handleChange` function already updates the `markdown` state whenever the user types. This, in turn, triggers a re-render of the component, which updates the preview. This is the essence of React’s reactivity.

Common Mistakes and How to Fix Them

Here are some common mistakes and how to avoid them:

  • Incorrect `marked` import: Ensure you’ve imported `marked` correctly: `import { marked } from ‘marked’;`. Typos can lead to import errors.
  • Forgetting to install `marked`: Make sure you’ve installed the `marked` library using `npm install marked` or `yarn add marked`.
  • Incorrect use of `dangerouslySetInnerHTML`: This is a powerful feature, but it needs to be used with caution. Make sure you trust the source of the HTML. In this case, since we’re using a trusted Markdown parser, it’s safe.
  • Not handling user input: The `handleChange` function is crucial. Make sure it’s correctly updating the `markdown` state with the value from the `textarea`. Incorrectly handling the `onChange` event will prevent the preview from updating.
  • Styling issues: If the preview looks unstyled, check your CSS file paths and ensure the styles are being applied correctly. Use your browser’s developer tools (usually accessed by right-clicking and selecting “Inspect”) to check for CSS errors or conflicts.

Enhancements and Further Development

This Markdown previewer is a solid starting point. Here are some ideas for further development:

  • Add a toolbar: Implement a toolbar with buttons to insert Markdown formatting (e.g., bold, italic, headings, links). This improves usability.
  • Implement live preview of images: Allow users to drag and drop images or upload them directly into the editor and see the image in the preview.
  • Add syntax highlighting for code blocks: Integrate a syntax highlighting library (like Prism.js or highlight.js) to make code blocks more readable.
  • Implement a dark/light mode toggle: Allow users to switch between light and dark themes for the editor and preview.
  • Add a feature to save and load Markdown files: Implement local storage or integrate with a backend to save and load Markdown content.
  • Implement a spell checker: Integrate a spell-checking library to improve writing accuracy.

Key Takeaways

This tutorial has walked you through building a functional Markdown previewer using React. You’ve learned about:

  • Creating a React component.
  • Managing component state with `useState`.
  • Handling user input with event listeners.
  • Using a Markdown parsing library.
  • Dynamically updating the UI.

FAQ

Here are some frequently asked questions:

  1. Why use `dangerouslySetInnerHTML`?

    React, by default, escapes HTML to prevent XSS attacks. However, in this case, we’re taking the output from a trusted Markdown parser. `dangerouslySetInnerHTML` allows us to inject the parsed HTML into the DOM safely.

  2. How can I add custom Markdown styles?

    You can add custom CSS styles to target specific Markdown elements in your `App.css` file. For example, you can style headings, paragraphs, and links to match your desired appearance.

  3. Can I use a different Markdown parser?

    Yes, there are other Markdown parsing libraries available, such as `markdown-it`. The core concepts of state management and event handling would remain the same; you would only need to change the import and the parsing function call.

  4. How do I deploy this application?

    You can deploy your React application to platforms like Netlify, Vercel, or GitHub Pages. These platforms provide simple deployment processes for React apps. You’ll typically run `npm run build` to create a production-ready build, and then deploy the contents of the `build` directory.

Building a Markdown previewer is an excellent project for both beginners and intermediate React developers. It combines fundamental concepts in a practical, user-friendly application. By understanding how to handle user input, manage state, and dynamically render content, you’ve gained valuable skills that can be applied to a wide range of React projects. Experiment with the enhancements, explore the libraries, and continue to refine your skills. The journey of a thousand lines of code begins with a single component. Happy coding!