Now that you understand JSX syntax, it's time to unleash its real power: embedding JavaScript expressions. This is what makes React components dynamic and interactive. In this lesson, you'll learn how to use curly braces to display variables, perform calculations, call functions, and create truly dynamic user interfaces.
The Magic of Curly Braces
In JSX, curly braces {} are your gateway to JavaScript land. Anything you put inside curly braces gets evaluated as JavaScript and the result is displayed in your component.
function Greeting() {
const name = "Sarah"
return (
<div>
{/* This is plain text */}
<h1>Hello, name</h1>
{/* This evaluates the variable */}
<h1>Hello, {name}</h1>
</div>
)
}
// Renders:
// Hello, name
// Hello, SarahThink of curly braces as an "escape hatch" from JSX into JavaScript. Whatever is inside gets evaluated and inserted into your markup.
💡 Remember
Curly braces work anywhere you can put content in JSX - in attributes, in text, and even in other JavaScript expressions!
Displaying Variables
The most basic use of curly braces is displaying variables. This works with all JavaScript data types:
Strings and Numbers
function UserProfile() {
const username = "johndoe"
const age = 28
const score = 95.5
const bio = "I love React!"
return (
<div>
<h2>@{username}</h2>
<p>Age: {age} years old</p>
<p>Score: {score}%</p>
<p>Bio: {bio}</p>
</div>
)
}Booleans and Null/Undefined
Here's something interesting: true, false, null, and undefined don't render anything:
function SpecialValues() {
const isTrue = true
const isFalse = false
const nothing = null
const notDefined = undefined
return (
<div>
<p>True: {isTrue}</p> {/* Renders: True: */}
<p>False: {isFalse}</p> {/* Renders: False: */}
<p>Null: {nothing}</p> {/* Renders: Null: */}
<p>Undefined: {notDefined}</p> {/* Renders: Undefined: */}
{/* To display boolean values, convert to string */}
<p>True: {String(isTrue)}</p> {/* Renders: True: true */}
<p>False: {String(isFalse)}</p> {/* Renders: False: false */}
</div>
)
}Why don't booleans render?
This is intentional! Booleans are typically used for conditional rendering (which we'll cover in the next lesson), not for display. If they rendered as "true" or "false", it would clutter your UI with unwanted text.
Arrays
When you put an array in curly braces, React renders all the elements together:
function ArrayExample() {
const fruits = ["Apple", "Banana", "Cherry"]
const numbers = [1, 2, 3, 4, 5]
return (
<div>
{/* Renders: AppleBananaCherry */}
<p>{fruits}</p>
{/* Renders: 12345 */}
<p>{numbers}</p>
{/* Better approach - we'll learn more about this later */}
<ul>
{fruits.map((fruit, index) => (
<li key={index}>{fruit}</li>
))}
</ul>
</div>
)
}Objects
Objects can't be rendered directly. You need to access their properties:
function PersonInfo() {
const person = {
name: "Alice",
age: 30,
occupation: "Developer"
}
return (
<div>
{/* ❌ This will cause an error */}
{/* <p>{person}</p> */}
{/* ✅ Access properties instead */}
<h2>{person.name}</h2>
<p>Age: {person.age}</p>
<p>Occupation: {person.occupation}</p>
</div>
)
}💡 Tip: Edit the code above and click "Run" to see your changes
JavaScript Expressions
Curly braces can contain any valid JavaScript expression. An expression is code that produces a value. Let's explore different types of expressions:
Mathematical Operations
function Calculator() {
const price = 99.99
const quantity = 3
const taxRate = 0.08
return (
<div>
<p>Price: ${price}</p>
<p>Quantity: {quantity}</p>
<p>Subtotal: ${price * quantity}</p>
<p>Tax: ${price * quantity * taxRate}</p>
<p>Total: ${price * quantity * (1 + taxRate)}</p>
{/* You can also format numbers */}
<p>Formatted: ${(price * quantity * (1 + taxRate)).toFixed(2)}</p>
</div>
)
}String Operations
function StringManipulation() {
const firstName = "john"
const lastName = "doe"
const email = "JOHN.DOE@EXAMPLE.COM"
return (
<div>
{/* Concatenation */}
<p>Full Name: {firstName + " " + lastName}</p>
{/* Template literals */}
<p>Full Name: {`${firstName} ${lastName}`}</p>
{/* String methods */}
<p>Capitalized: {firstName.charAt(0).toUpperCase() + firstName.slice(1)}</p>
<p>Uppercase: {firstName.toUpperCase()}</p>
<p>Email: {email.toLowerCase()}</p>
{/* String length */}
<p>Name has {firstName.length} letters</p>
</div>
)
}Comparison and Logical Operations
function Comparisons() {
const score = 85
const age = 20
const isStudent = true
return (
<div>
{/* Comparison results (convert to string to see them) */}
<p>Passed: {String(score >= 60)}</p>
<p>Perfect Score: {String(score === 100)}</p>
<p>Adult: {String(age >= 18)}</p>
{/* Logical operations */}
<p>Student Discount: {String(isStudent && age < 25)}</p>
<p>Special Access: {String(score > 90 || isStudent)}</p>
</div>
)
}Ternary Operator
The ternary operator is one of the most useful tools in JSX. It lets you choose between two values based on a condition:
function StatusMessage() {
const isLoggedIn = true
const messageCount = 5
const temperature = 25
return (
<div>
{/* Basic ternary */}
<p>{isLoggedIn ? "Welcome back!" : "Please log in"}</p>
{/* With variables */}
<p>You have {messageCount > 0 ? messageCount : "no"} messages</p>
{/* Nested ternary (use sparingly!) */}
<p>
Temperature: {
temperature > 30 ? "Hot" :
temperature > 20 ? "Warm" :
temperature > 10 ? "Cool" : "Cold"
}
</p>
{/* With JSX elements */}
{isLoggedIn ? (
<button>Logout</button>
) : (
<button>Login</button>
)}
</div>
)
}📖 Ternary Operator Syntax
condition ? valueIfTrue : valueIfFalse
Think of the ? as asking "is this true?" and the : as meaning "otherwise use this instead"
Function Calls
function FunctionCalls() {
const formatCurrency = (amount) => {
return new Intl.NumberFormat('en-US', {
style: 'currency',
currency: 'USD'
}).format(amount)
}
const getGreeting = () => {
const hour = new Date().getHours()
if (hour < 12) return "Good morning"
if (hour < 18) return "Good afternoon"
return "Good evening"
}
const calculateDiscount = (price, percentage) => {
return price - (price * percentage / 100)
}
return (
<div>
<h1>{getGreeting()}!</h1>
<p>Original Price: {formatCurrency(99.99)}</p>
<p>Discounted: {formatCurrency(calculateDiscount(99.99, 20))}</p>
<p>Random: {Math.random().toFixed(2)}</p>
<p>Current Time: {new Date().toLocaleTimeString()}</p>
</div>
)
}Array Methods
function ArrayMethods() {
const numbers = [1, 2, 3, 4, 5]
const names = ["Alice", "Bob", "Charlie"]
return (
<div>
{/* Array methods that return values */}
<p>Sum: {numbers.reduce((a, b) => a + b, 0)}</p>
<p>Average: {numbers.reduce((a, b) => a + b, 0) / numbers.length}</p>
<p>Max: {Math.max(...numbers)}</p>
<p>Count: {names.length}</p>
<p>Joined: {names.join(", ")}</p>
<p>First name: {names[0]}</p>
<p>Last name: {names[names.length - 1]}</p>
</div>
)
}💡 Tip: Edit the code above and click "Run" to see your changes
Expressions in Attributes
You can use JavaScript expressions not just in content, but also in attributes:
Dynamic URLs and Sources
function DynamicAttributes() {
const userId = 123
const imageName = "profile"
const imageFormat = "jpg"
const isExternal = true
return (
<div>
{/* Dynamic src */}
<img src={`/images/${imageName}.${imageFormat}`} alt="Profile" />
{/* Dynamic href */}
<a href={`/users/${userId}`}>View Profile</a>
{/* Conditional attributes */}
<a
href="https://example.com"
target={isExternal ? "_blank" : "_self"}
rel={isExternal ? "noopener noreferrer" : undefined}
>
Link
</a>
</div>
)
}Dynamic Class Names
function DynamicClasses() {
const isActive = true
const isLarge = false
const theme = "dark"
const size = "md"
return (
<div>
{/* Simple conditional class */}
<button className={isActive ? "active" : "inactive"}>
Button
</button>
{/* Multiple classes with template literal */}
<div className={`btn btn-${size} ${isActive ? "active" : ""}`}>
Multi-class
</div>
{/* Complex conditional classes */}
<div className={`
base-class
${isActive ? "active" : "inactive"}
${isLarge ? "large" : "small"}
theme-${theme}
`.trim()}>
Complex
</div>
</div>
)
}Dynamic Inline Styles
function DynamicStyles() {
const primaryColor = "#6366f1"
const fontSize = 18
const isHighlighted = true
const progress = 75
return (
<div>
{/* Basic dynamic styles */}
<h1 style={{
color: primaryColor,
fontSize: `${fontSize}px`
}}>
Heading
</h1>
{/* Conditional styles */}
<p style={{
backgroundColor: isHighlighted ? "yellow" : "transparent",
fontWeight: isHighlighted ? "bold" : "normal"
}}>
Text
</p>
{/* Progress bar */}
<div style={{
width: "100%",
height: "20px",
backgroundColor: "#e5e7eb"
}}>
<div style={{
width: `${progress}%`,
height: "100%",
backgroundColor: primaryColor,
transition: "width 0.3s"
}} />
</div>
</div>
)
}💡 Style Objects Tip
You can create style objects outside JSX for reusability:const headingStyle = {{ color: 'blue', fontSize: '24px' }}<h1 style={headingStyle}>Title</h1>
Template Literals in JSX
Template literals (backticks) are incredibly useful in JSX for creating dynamic strings:
function TemplateLiterals() {
const firstName = "John"
const lastName = "Doe"
const age = 28
const city = "New York"
const country = "USA"
return (
<div>
{/* Simple interpolation */}
<h1>Hello, {`${firstName} ${lastName}`}!</h1>
{/* Multiple variables */}
<p>{`I am ${age} years old and live in ${city}, ${country}`}</p>
{/* With expressions */}
<p>{`Next year I'll be ${age + 1} years old`}</p>
{/* In attributes */}
<div className={`user-${firstName.toLowerCase()}-profile`}>
Profile
</div>
{/* Multi-line (though rarely needed) */}
<p>{`
Name: ${firstName} ${lastName}
Age: ${age}
Location: ${city}, ${country}
`}</p>
</div>
)
}What You Can't Put in Curly Braces
Remember: curly braces can only contain expressions (code that returns a value), not statements (code that performs actions).
Statements That Don't Work
function InvalidExamples() {
return (
<div>
{/* ❌ if/else statements don't work */}
{if (true) { "hello" }}
{/* ❌ for loops don't work */}
{for (let i = 0; i < 5; i++) { console.log(i) }}
{/* ❌ while loops don't work */}
{while (true) { break }}
{/* ❌ variable declarations don't work */}
{const x = 5}
{/* ❌ switch statements don't work */}
{switch(value) { case 1: "one" }}
</div>
)
}Use These Instead
function ValidAlternatives() {
const numbers = [1, 2, 3, 4, 5]
const score = 85
return (
<div>
{/* ✅ Use ternary instead of if/else */}
{score >= 60 ? "Pass" : "Fail"}
{/* ✅ Use map instead of for loop */}
{numbers.map((num, index) => (
<p key={index}>{num}</p>
))}
{/* ✅ Use IIFE for complex logic */}
{(() => {
const result = score >= 90 ? "A" :
score >= 80 ? "B" :
score >= 70 ? "C" : "F"
return result
})()}
{/* ✅ Or better: extract to a variable */}
{/* (define grade before return) */}
</div>
)
}Pro Tip: Keep It Simple
If your expression is getting too complex, extract it to a variable or function before the return statement. This makes your JSX cleaner and easier to read!
Best Practices for JSX Expressions
Follow these guidelines to write clean, maintainable JSX:
1. Extract Complex Logic
// ❌ Too complex in JSX
function BadExample({ user }) {
return (
<div>
{user.firstName.charAt(0).toUpperCase() + user.firstName.slice(1) + " " +
user.lastName.charAt(0).toUpperCase() + user.lastName.slice(1)}
</div>
)
}
// ✅ Extract to variable
function GoodExample({ user }) {
const capitalizeWord = (word) => {
return word.charAt(0).toUpperCase() + word.slice(1)
}
const fullName = `${capitalizeWord(user.firstName)} ${capitalizeWord(user.lastName)}`
return <div>{fullName}</div>
}2. Avoid Nested Ternaries
// ❌ Hard to read
{status === 'loading' ? <Spinner /> :
status === 'error' ? <Error /> :
status === 'success' ? <Data /> : null}
// ✅ Use if/else before return
function BetterExample({ status }) {
if (status === 'loading') return <Spinner />
if (status === 'error') return <Error />
if (status === 'success') return <Data />
return null
}
// ✅ Or use a mapping object
const componentMap = {
loading: <Spinner />,
error: <Error />,
success: <Data />
}
return componentMap[status] || null3. Use Meaningful Variable Names
// ❌ Unclear
const x = users.filter(u => u.age > 18).length
// ✅ Clear and descriptive
const adultUserCount = users.filter(user => user.age > 18).length4. Format Long Expressions
// ❌ Hard to read
<div className={`container ${isActive ? "active" : ""} ${isLarge ? "large" : "small"} ${theme === "dark" ? "dark-mode" : ""}`}>
// ✅ Break into multiple lines
<div className={`
container
${isActive ? "active" : ""}
${isLarge ? "large" : "small"}
${theme === "dark" ? "dark-mode" : ""}
`.trim()}>
// ✅ Or use a variable
const containerClasses = [
"container",
isActive && "active",
isLarge ? "large" : "small",
theme === "dark" && "dark-mode"
].filter(Boolean).join(" ")
<div className={containerClasses}>💡 Tip: Edit the code above and click "Run" to see your changes
Key Takeaways
- Curly braces
{}let you embed JavaScript expressions in JSX - You can use variables, math operations, function calls, and more
- Booleans, null, and undefined don't render (by design)
- Objects can't be rendered directly - access their properties instead
- Template literals are great for creating dynamic strings
- Ternary operators are perfect for conditional values in JSX
- Use expressions in attributes for dynamic className, src, href, etc.
- Only expressions work in curly braces, not statements
- Extract complex logic to variables or functions before the return
- Keep JSX expressions simple and readable
What's Next?
You now know how to make your React components dynamic using JavaScript expressions and variables. But what if you want to show or hide entire sections of your UI based on conditions? What if you need different content for different scenarios?
That's where conditional rendering comes in! In the next lesson, you'll learn all the techniques for rendering content conditionally - using if/else logic, ternary operators, logical AND operators, and more. Get ready to build truly dynamic interfaces! 🎯