MDX Notes
The fundamentals of JSX syntax inside MDX — expressions, HTML differences, self-closing tags, fragments, and the gotchas that trip people up.
JSX is what gives you React powers inside your Markdown. It looks like HTML, lives in JavaScript, and lets you drop interactive components right into your content. Once you get the basics down, mixing Markdown and JSX feels natural.
What is JSX?
JSX looks like HTML but it's actually JavaScript. React uses it to describe what the UI should look like. Under the hood, it gets compiled to function calls:
// This JSX:
<h1 className="title">Hello, MDX!</h1>
// Becomes this JavaScript:
React.createElement('h1', { className: 'title' }, 'Hello, MDX!')In MDX, you write JSX directly alongside Markdown. No special delimiters needed. The compiler figures out what's Markdown and what's JSX.
How JSX Works Inside MDX
Any line starting with < that looks like a valid JSX element gets treated as JSX instead of Markdown. So you can freely mix the two:
The MDX compiler handles both in a single pass.
JSX Expressions with Curly Braces
This is the big one. Curly braces {} let you embed any JavaScript expression inside JSX:
What Can Go Inside {}?
Any JavaScript expression — meaning anything that produces a value:
Important: You cannot use statements (if/else,forloops, variable declarations) inside{}. Only expressions. If you need conditional logic, use a ternary.
JSX vs HTML Differences
JSX looks like HTML but has some critical differences. These will bite you if you don't know about them.
className vs class
{/* ✅ Correct in JSX */}
<div className="container">Content</div>
{/* ❌ Wrong - 'class' is a reserved word in JavaScript */}
<div class="container">Content</div>htmlFor vs for
{/* ✅ Correct in JSX */}
<label htmlFor="email">Email:</label>
<input id="email" type="email" />
{/* ❌ Wrong - 'for' is a reserved word in JavaScript */}
<label for="email">Email:</label>Other Key Differences
| HTML Attribute | JSX Equivalent |
|---|---|
class | className |
for | htmlFor |
tabindex | tabIndex |
onclick | onClick |
onchange | onChange |
readonly | readOnly |
maxlength | maxLength |
colspan | colSpan |
Style Attribute
In JSX, style takes an object with camelCase properties — not a CSS string:
{/* ✅ Correct - object with camelCase properties */}
<div style={{ backgroundColor: 'blue', fontSize: '16px', marginTop: '1rem' }}>
Styled content
</div>
{/* ❌ Wrong - CSS string doesn't work */}
<div style="background-color: blue; font-size: 16px;">
This won't work in JSX
</div>Self-Closing Tags
In HTML, elements like <img>, <br>, and <input> don't need closing tags. In JSX, every element must be closed — either with a closing tag or self-closing syntax:
{/* ✅ Self-closing tags in JSX */}
<img src="/photo.jpg" alt="A photo" />
<br />
<input type="text" placeholder="Enter name" />
<hr />
{/* ✅ Also valid - with closing tag */}
<div></div>
<span></span>
{/* ❌ Wrong - unclosed tags cause errors */}
<img src="/photo.jpg" alt="A photo">
<br>
<input type="text">Fragments
When you need to return multiple elements without adding an extra wrapper <div>, use Fragments:
import { Fragment } from 'react'
{/* Using Fragment component */}
<Fragment>
<h2>First heading</h2>
<p>First paragraph</p>
</Fragment>
{/* Short syntax with empty tags */}
<>
<h2>Second heading</h2>
<p>Second paragraph</p>
</>Fragments are handy when you want to group JSX without adding DOM nodes:
Comments in JSX
JSX comments look different from HTML comments:
Practical Tips
<div className="tip-box">
Tip 1: Use a linter or IDE plugin that catches mistakes like class instead of className. You'll save yourself a lot of debugging.
Tip 2: JSX expressions must return a single root element. If you have siblings, wrap them in a Fragment.
Tip 3: Boolean attributes work differently. Use disabled={true} or just disabled — not disabled="disabled".
</div>
Common Pitfalls
- Forgetting to close tags — Every tag must be closed in JSX, including
<img />,<br />,<hr /> - Using
classinstead ofclassName— The most common mistake when switching from HTML to JSX - Putting statements in
{}— Only expressions work. Use ternary operators instead of if/else - Missing keys in lists — When using
.map(), always add a uniquekeyprop - Adjacent JSX elements — Multiple elements need a Fragment or parent div wrapper
Summary
JSX in MDX is just React's component syntax mixed into your content. Remember: className not class, curly braces for expressions, close all your tags, and use Fragments when you need to group without wrapping. That's the foundation — everything else builds on these basics.
Exam Focus
Revise definitions, diagrams, examples, and short-answer points for JSX Basics in MDX.
Interview Use
Prepare one clear explanation, one practical example, and one common mistake for this MDX Tutorial topic.
Search Terms
mdx-tutorial, mdx tutorial, mdx, tutorial, jsx, basics, jsx basics in mdx
Related MDX Tutorial Topics