When building frontend interfaces, you often find situations where you want to show or hide elements based on certain conditions. You might think of using if/else statements, but there's a more compact way to achieve the same result — using ternary and logical AND operators. In React, you can use these operators to conditionally render components or JSX elements. In this topic, we'll explore how these operators work in general and see practical examples of how to use them when creating React applications.
Conditional rendering
Conditional rendering in React enables you to selectively display elements on the UI based on conditions defined in your code. These conditions can depend on the values of variables, computation results, or the state of your application.
You will often find situations where this technique becomes necessary. For instance, you may want to display a login page to logged-out users while allowing authenticated users to see the app's content. Another use case is when you send a GET request to the server, where you can show a "loading" message while waiting for the response. Once you receive the response, you can hide the loader and display the received data.
Conditional rendering helps you adjust the content and appearance of your application dynamically. It responds to user interactions, data availability, or other relevant factors to create more interactive, personalized, and responsive user interfaces.
There are three common ways to implement conditional rendering in React:
ifstatementTernary operator
Logical AND
Let's delve into these techniques in detail.
If statement
The if statement will feel familiar to you if you've previously used pure JS. It allows you to set some kind of condition inside the parentheses; if the expression evaluates to true, the code enclosed within curly braces will execute.
Login function
Try to build a logging mechanism in an app. You need to create two components — UserGreeting and DefaultGreeting. The first one displays if the user is logged in. It is structured as a simple "Welcome back" message inside an h2 tag:
// src/components/user-greeting/UserGreeting.jsx
import React from 'react'
function UserGreeting() {
return (
<h1>Welcome back!</h1>
)
}
export default UserGreetingThe second component displays a "Let's log you in!" message and is shown to any visitor who is logged out. It looks like this:
// src/components/default-greeting/DefaultGreeting.jsx
import React from 'react'
function DefaultGreeting() {
return (
<h1>Let's log you in!</h1>
)
}
export default DefaultGreetingFinally, set up a condition inside the App component that manages the whole logic. First, import both components. Then create a state variable that will determine which component should be rendered. In this case, we're using the useState hook, but you could also use a standard constant variable set to true or false.
App component:
// src/components/app/App.jsx
import React, { useState } from 'react';
import UserGreeting from '../user-greeting/UserGreeting';
import DefaultGreeting from '../default-greeting/DefaultGreeting';
function App() {
const [isLogged] = useState(true);
if (isLogged) {
return <UserGreeting />;
}
return <DefaultGreeting />;
}
export default App;This code checks whether the isLogged variable is true. If it is, it'll render the UserGreeting component; otherwise, it renders the DefaultGreeting.
Open the page in the browser, toggle your code between true and false, and observe how it changes dynamically. You can use conditional rendering with regular JSX elements, not just entire components. Since our app is small and the components consist of a single h2 element, we can simplify our app a bit. Look:
import React, { useState } from 'react';
function App() {
const [isLogged] = useState(true);
if (isLogged) {
return <h2>Welcome back!</h2>;
}
return <h2>Let's log you in!</h2>;
}
export default App;We got rid of the imported components and replaced them with the actual strings. If you check the page in the browser, you'll see that it works the same.
When isLogged is true, the page shows this:
When isLogged is false, the page shows this:
Online status
If you use any social media, you've likely noticed that many platforms display user status or last activity. We can create a simplified version of this. Suppose you have a user object with name and isOnline properties:
const [user] = useState({name: 'Anisa', isOnline: true});After that, check if the isOnline property is set to true. If it is, render the statement "Anisa is now online!", otherwise display "Anisa went offline". Here's the full code, similar to what we had previously:
import React, { useState } from 'react';
function App() {
const [user] = useState({name: 'Anisa', isOnline: true});
if (user.isOnline) {
return <h2>{user.name} is now online!</h2>;
}
return <h2>{user.name} went offline</h2>;
}
export default App;Logical operators
The logical AND operator (&&) evaluates the truthiness of two values. If both of them return true, the result of the operation will also be true. However, if one of the values is false, the entire expression will be set to false.
Suppose we receive a users array with some data from the backend, and we want to display it on the page. However, we are not always 100% sure if the server will respond to our query without any errors. In that case, let's first check if the users array exists, and only after that, display it.
import React from 'react';
function App() {
const users = [
{ id: 1, name: 'Brian', age: 23 },
{ id: 2, name: 'Mila', age: 20 },
{ id: 3, name: 'Jane', age: 17 },
];
return (
<>
{users.length > 0 &&
users.map((user) => (
<div key={user.id}>
{user.name}, {user.age} y.o.
</div>
))}
</>
);
}
export default App;In this example, we check if the users array's length is greater than zero, indicating it exists and contains some items. If the length returns a truthy value, we render each user's name and age. The output:
In this example, we only had one logical AND operator, but there can be more than one, depending on the logic of your application. Suppose we have another state variable that we need to consider when rendering the list of users. Then our code would look like this:
condition1 && condition2 && condition3And here's a React example:
import React, { useState } from 'react';
function App() {
const [isLogged] = useState(true);
const users = [
{ id: 1, name: 'Brian', age: 23 },
{ id: 2, name: 'Mila', age: 20 },
{ id: 3, name: 'Jane', age: 17 },
];
return (
<>
{isLogged && users.length > 0 &&
users.map((user) => (
<div key={user.id}>
{user.name}, {user.age} y.o.
</div>
))}
</>
);
}
export default App;In this code, we additionally check the isLogged variable. If it's true, React will then check the length of the array. If that's also true, the list will be rendered. In short, we need to pass two conditions to render the users data.
Just like in JavaScript, you can also negate conditions by placing the ! mark before an expression, or use the logical AND (&&) in combination with the logical OR (||) operator.
Let's change the user array a bit, as follows:
const users = [
{ id: 1, name: 'Brian', favFood: 'oreo' },
{ id: 2, name: 'Mila', favFood: 'kitkat' },
{ id: 3, name: 'Jane', favFood: 'broccoli' },
];You want to determine who has a sweet tooth. To do this, cycle through the array and check the favFood property. If it's equal to "oreo" or "kitkat", declare the user has a sweet tooth; otherwise, call them vegan. In this example, you'll need to use the logical OR operator:
{users.map((user) => ( <div key={user.id}>
{user.name} is {user.favFood === 'oreo' || user.favFood === 'kitkat' ? 'sweet tooth' : 'vegan'}
</div>
))}The output:
Ternary operator
The ternary operator offers a concise way to write conditional if/else statements in JavaScript. It takes three operands: a condition, an expression to evaluate if the condition is true, and an expression to evaluate if the condition is false. The syntax is as follows:
condition ? expressionIfTrue : expressionIfFalseLet's make our app a bit more complex and instead of using predefined users data, we can fetch it from an API, like JSONPlaceholder. The logic for getting data from the backend is usually placed inside the useEffect hook. Don't worry if you're unfamiliar with it; for now, think of it as a place for data fetching. Once we receive the data, we save it to the users array using the setUser function. The useState hook allows us to dynamically update the state. Again, don't worry if some of the syntax seems strange. Try to focus on the ternary operator logic:
import React, { useEffect, useState } from 'react';
function App() {
const [users, setUsers] = useState([]);
useEffect(() => {
fetch('https://jsonplaceholder.typicode.com/users')
.then((response) => response.json())
.then((data) => setUsers(data));
})
return (
<>
{users.length > 0 ?
users.map((user) => (
<div key={user.id}>
{user.name}
</div>
)) : <p>Loading...</p>}
</>
);
}
export default App;We ask React to check whether users.length is greater than zero. If it is, we instruct it to render our data; otherwise, we tell it to display the "Loading" message. You could also write this in the following way:
{!users.length ? <p>Loading...</p> : users.map((user) => <div>{user.name}</div>)}If the length returns a falsey value, the app shows the loading message; otherwise, it shows the list. Both variants result in the same output, so you can use either. The output:
Did you see it? It briefly showed "Loading" before displaying the list. By the way, you can create a more sophisticated loader using CSS animations or even use an additional library.
Chained conditions
Until now, we've explored how to render conditionally using two expressions. However, there can be situations where more than one condition is needed. In these instances, you can link conditions together; they function similarly to an if/else if/else structure.
Let's design motivational messages for users when they finish the quiz. The following table illustrates the correlation between scores and the corresponding messages:
Score | Message |
10 | Keep up the great work! |
5 | Halfway to success! |
< 5 | There are no failures – just experiences and your reactions to them! |
Here's the code:
import React, { useState } from 'react';
function App() {
const [users] = useState([
{ id: 1, name: 'Brian', score: 10 },
{ id: 2, name: 'Mila', score: 5 },
{ id: 3, name: 'Jane', score: 3 },
])
const maxScore = 10;
return (
<h2>
{users.map(user => <div key={user.id}>{user.name}, {user.score === maxScore
? 'Keep up the great work!'
: user.score === maxScore / 2
? 'Half way to success!'
: 'There are no failures – just experiences and your reactions to them!'}</div>)}
</h2>
);
}
export default App;In this example, we examine each user in the array and assess the score property: If it equals 10, we display the message "Keep up the great work!". If it equals 5, we change the message to "Halfway to success!". Any score less than 5 will trigger the default message: "There are no failures – just experiences and your reactions to them!"
Conclusion
Conditional rendering in React.js functions similarly to how conditions operate in JavaScript. By using JavaScript operators like if, the ternary operator ? :, or the logical AND operator &&, you can design elements that depict the current state. React then updates the UI to align with these elements. You can also chain the ternary and logical AND operators to create a long list of conditions or combine them with the use of negated expressions and the logical OR operator.