MDX Notes
How to pass props to React components in MDX — strings, numbers, objects, arrays, spread props, TypeScript interfaces, and common gotchas.
Props are how you send data into your components. Think of them like function arguments — you stick key-value pairs on a component tag, and the component uses them however it wants.
What Are Props?
Props flow one way: parent → child. In MDX, you write them on component tags just like HTML attributes, except you've got full JavaScript at your disposal:
{/* Props are key-value pairs on the component tag */}
<Alert type="warning" message="Be careful!" dismissible={true} />The component receives these as a single object:
// Inside the Alert component
function Alert(props) {
// props = { type: "warning", message: "Be careful!", dismissible: true }
return <div className={`alert alert-${props.type}`}>{props.message}</div>
}Passing Different Data Types
Strings
Strings are the simplest — just use quotes, no curly braces:
{/* Simple string props */}
<Button label="Click me" variant="primary" size="large" />
{/* Multi-word strings */}
<PageHeader title="Welcome to Our Documentation" subtitle="Everything you need to know" />
{/* String with special characters */}
<CodeSnippet code="const x = 'hello'" language="javascript" />Numbers
Numbers need curly braces because they're JavaScript values, not strings:
{/* Number props */}
<ProgressBar value={75} max={100} />
<Pagination currentPage={3} totalPages={12} />
<Avatar size={48} borderRadius={24} />
{/* Calculations work too */}
<Grid columns={4} gap={16 * 2} />Booleans
Booleans have a nice shorthand — just naming the prop means true:
{/* Explicit boolean values */}
<Modal open={true} closable={false} />
{/* Shorthand: presence = true */}
<Input required disabled placeholder="Read only" />
{/* The above is equivalent to: */}
<Input required={true} disabled={true} placeholder="Read only" />
{/* To pass false, you must be explicit */}
<Sidebar collapsible={false} />Objects
Objects get double braces — the outer pair is the JSX expression wrapper, the inner pair is the object literal:
{/* Object props */}
<UserProfile
user={{ name: "Alice", age: 30, role: "Developer" }}
settings={{ theme: "dark", notifications: true }}
/>
{/* Style objects */}
<Card style={{ backgroundColor: '#f5f5f5', padding: '1.5rem', borderRadius: '8px' }} />
{/* Complex nested objects */}
<Chart
config={{
type: 'line',
options: {
responsive: true,
scales: { y: { beginAtZero: true } }
}
}}
/>Arrays
Same curly brace pattern as objects:
Functions
You can pass event handlers, callbacks, render functions — anything callable:
Default Props
Defaults give your component sensible fallback values when a prop isn't passed:
Default Props with defaultProps (Legacy Pattern)
// In a separate component file
function Button({ label, variant, size }) {
return <button className={`btn btn-${variant} btn-${size}`}>{label}</button>
}
Button.defaultProps = {
variant: 'primary',
size: 'medium'
}Note: The defaultProps pattern is being deprecated. Use default parameter values in the function signature instead.The Children Prop
children is whatever you put between the opening and closing tags of a component:
Multiple Children Slots
When you need more than one content area, use named props:
Spread Props
The spread operator (...) dumps all properties of an object as individual props:
Combining Spread with Individual Props
export const baseInputProps = {
className: "form-input",
autoComplete: "off"
}
{/* Spread base props and add/override specific ones */}
<input {...baseInputProps} type="email" placeholder="Email" className="form-input email-input" />Note: Later props override earlier ones. In the example above,classNamefrom the spread gets overridden by the explicitclassName.
Destructuring Props
Destructuring pulls out specific props right in the function signature. It's cleaner and gives you defaults in one place:
The ...rest pattern captures everything you didn't explicitly name. Super handy for passing through DOM attributes like id or data-*.
TypeScript Props Interfaces
TypeScript catches prop mistakes at compile time instead of at 2am in production:
Usage in MDX:
Practical Tips
<div className="tips">
Tip 1: Keep prop interfaces simple in MDX files. Complex data should live in separate data files, not inline.
Tip 2: Use descriptive prop names. <Card color="red"> is way better than <Card c="r">.
Tip 3: Prefer primitive props (strings, numbers, booleans) for simple components. Save object props for complex configs.
Tip 4: Don't pass props the component doesn't need. Every prop is a contract.
</div>
Common Pitfalls
- Forgetting curly braces for non-string values —
count="5"passes a string,count={5}passes a number - Mutating props — Props are read-only. Never modify them inside a component
- Passing objects inline in render —
style={{ color: 'red' }}creates a new object every render; extract it if performance matters - Missing required props — Use TypeScript or PropTypes to catch this early
- Over-spreading —
{...props}on DOM elements can pass invalid HTML attributes and trigger warnings
Summary
Props are how your MDX content talks to React components. Once you're comfortable with the different data types, defaults, children, spread, and TypeScript interfaces, you can build flexible component libraries that make your MDX content way more powerful.
Exam Focus
Revise definitions, diagrams, examples, and short-answer points for Passing Props 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, passing, props, passing props in mdx
Related MDX Tutorial Topics