Skip to main content

Mastering Markdown in React

· 5 min read
Henri Courdent

Markdown is the minimalist's dream for text formatting—no fancy editors or HTML acrobatics needed. Just a few symbols like asterisks for bold or hashes for headings, and you're off to the races. It's the go-to for bloggers and devs alike, perfect for whipping up websites, blogs, docs, and more. This article itself is written in Markdown.

Born for the web, Markdown is the darling of platforms like GitHub, Stack Overflow, and Reddit. In this guide, we'll explore how to use Markdown in React applications using the react-markdown package.

Not in Windmill

Please note that this is a general tutorial that does not cover any aspect of the product hosting this article: Windmill. To see how Windmill offers alternatives for your React applications, refer to the last section.

Markdown basics

Let's dive into the essentials of Markdown syntax:

Headings

To create headings, use number signs (#). The more signs, the smaller the heading:

# Big Boss Heading
## Slightly Smaller Boss
### Middle Management
#### Team Lead
##### Senior Dev
###### Junior Dev

This will be rendered as:

Big Boss Heading

Slightly Smaller Boss

Middle Management

Team Lead

Senior Dev
Junior Dev

Remember to include a space between the hash and your text.

Lists

Markdown supports both ordered and unordered lists:

Ordered Lists:

1. Banana
2. Kiwi

This will be rendered as:

  1. Banana
  2. Kiwi

Unordered Lists:

- Banana
- Kiwi

* Banana
* Kiwi

+ Banana
+ Kiwi

This will be rendered as:

  • Banana
  • Kiwi
  • Banana
  • Kiwi
  • Banana
  • Kiwi

Create links using square brackets for text and parentheses for the URL:

[Windmill](https://www.windmill.dev/)

This will be rendered as:

Windmill

Images

Add images with an exclamation mark, alt text in brackets, and the path in parentheses:

![Windmill logo](https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTXrLXCq_Qrr9X9Yavf8jF3AonwSqLgHmAIKA&s)

This will be rendered as:

Windmill logo

Typography

Style text using asterisks:

**Bold move**
*Italic flair*

This will be rendered as:

Bold move Italic flair

Understanding react-markdown

The react-markdown package transforms Markdown into React components that render as HTML in your app. Unlike other libraries that use dangerouslySetInnerHTML, react-markdown creates a syntax tree for a virtual DOM, making it both safer and more efficient.

Installation

First, ensure you have Node.js installed, then create a new React project:

npx create-react-app markdown-app
cd markdown-app
npm install react-markdown

Basic implementation

Here's a simple example of using react-markdown:

import React from 'react'
import ReactMarkdown from 'react-markdown'

export default function App() {
return (
<div>
<ReactMarkdown>
# Hello, *world*!
</ReactMarkdown>
</div>
)
}

Basic implementation

Advanced features

Custom components

You can customize how specific Markdown elements are rendered using the components prop:

import React from 'react'
import ReactMarkdown from 'react-markdown'

const CustomH1 = ({node, ...props}) => (
<h1 style={{color: 'blue'}} {...props} />
)

export default function App() {
return (
<div>
<ReactMarkdown
components={{
h1: CustomH1
}}
>
# This heading will be blue
</ReactMarkdown>
</div>
)
}

Custom components

Plugins and extensions

React Markdown supports various plugins through the unified ecosystem. Here's how to add syntax highlighting with react-syntax-highlighter:

npm install react-syntax-highlighter

Implementation example:

import React from 'react'
import ReactMarkdown from 'react-markdown'
import {Prism as SyntaxHighlighter} from 'react-syntax-highlighter'
import {dark} from 'react-syntax-highlighter/dist/esm/styles/prism'

export default function App() {
const markdown = `\`\`\`javascript
const hello = 'world';
console.log(hello);
\`\`\``

return (
<ReactMarkdown
components={{
code({node, inline, className, children, ...props}) {
const match = /language-(\w+)/.exec(className || '')
return !inline && match ? (
<SyntaxHighlighter
style={dark}
language={match[1]}
PreTag="div"
{...props}
>
{String(children).replace(/\n$/, '')}
</SyntaxHighlighter>
) : (
<code className={className} {...props}>
{children}
</code>
)
}
}}
>
{markdown}
</ReactMarkdown>
)
}

Syntax highlighter

You can customize how images and links are rendered:

import React from 'react'
import ReactMarkdown from 'react-markdown'

export default function App() {
return (
<ReactMarkdown
components={{
img: ({node, ...props}) => (
<div style={{ textAlign: 'center', margin: '20px 0' }}>
<img
{...props}
style={{
maxWidth: '70%',
borderRadius: '8px',
boxShadow: '0 4px 8px rgba(0,0,0,0.1)',
transition: 'transform 0.2s',
cursor: 'pointer',
}}
onMouseOver={(e) => e.target.style.transform = 'scale(1.05)'}
onMouseOut={(e) => e.target.style.transform = 'scale(1)'}
loading="lazy"
onError={(e) => {
e.target.src = 'fallback-image-url.jpg'
e.target.alt = 'Failed to load image'
}}
/>
</div>
),
a: ({node, children, href, ...props}) => (
<a
href={href}
target="_blank"
rel="noopener noreferrer"
style={{
color: '#0066cc',
textDecoration: 'none',
borderBottom: '1px solid transparent',
transition: 'border-bottom-color 0.2s',
}}
onMouseOver={(e) => e.target.style.borderBottomColor = '#0066cc'}
onMouseOut={(e) => e.target.style.borderBottomColor = 'transparent'}
onClick={() => console.log(`Link clicked: ${href}`)}
{...props}
>
{children} ↗️
</a>
)
}}
>
# Handling images and links

![Example Image](https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTXrLXCq_Qrr9X9Yavf8jF3AonwSqLgHmAIKA&s)

[Visit Windmill](https://www.windmill.dev/)
</ReactMarkdown>
)
}

Build custom UIs with Windmill

This completes our guide on using React Markdown in your applications.

For teams looking to create content-rich applications, Windmill's App editor offers a compelling alternative to developing custom apps in React. While React requires coding Markdown implementations from scratch and managing complexities like component styling and rendering, Windmill simplifies these aspects.

The low-code App builder is designed to create custom User Interfaces by combining drag-and-drop functionality with code. It comes with +60 components that you can style and link to scripts and flows. We even have a ... Markdown component. Additionally, it supports the integration of custom React components and even entire React apps, providing flexibility for more advanced development needs.

This enables faster development with less overhead, making it a practical choice for projects where quick deployment and ease of maintenance are priorities.


Windmill Logo
Windmill is an open-source and self-hostable serverless runtime and platform combining the power of code with the velocity of low-code. We turn your scripts into internal apps and composable steps of flows that automate repetitive workflows.

You can self-host Windmill using a docker compose up, or go with the cloud app.