Conditional Rendering

Account Required

This free lesson is available if you sign in.
If you don't have an account, you can sign up for free.

Conditional Rendering

Sign in to access this content

You must sign in to access this content.
If you don't have an account you can sign up for free!

Falsy values in JavaScript

A quick recap of something we learnt in our JavaScript course, there are only a few Falsy values in JavaScript.

// All of these behave like "false"
// Hence called "Falsy"
if (false) {
console.log('I will not execute');
}
if (null) {
console.log('I will not execute');
}
if (undefined) {
console.log('I will not execute');
}
if ('') {
console.log('I will not execute');
}
if (0) {
console.log('I will not execute');
}
if (NaN) {
console.log('I will not execute');
}

React and Falsy Values

React doesn't render falsy values, except for numbers. This is shown in this demo:

App.tsx
export default function App() {
return (
<>
<div>false: {false}</div>
<div>null: {null}</div>
<div>undefined: {undefined}</div>
<div>'': {""}</div>
<div>0: {0}</div>
<div>NaN: {NaN}</div>
</>
);
}

Standard Number Rendering

Because React always renders a number (even when falsy), it allows for easier development experience as demonstrated in this demo:

App.tsx
import { useState } from "react";

export default function App() {
const [count, setCount] = useState(0);
const inc = () => setCount((clicks) => clicks + 1);
const dec = () => setCount((clicks) => clicks - 1);

return (
<>
<div>
<button onClick={inc}>+</button>
<button onClick={dec}>-</button>
</div>
<p>Count: {count}</p>
</>
);
}

JavaScript && chaining

A quick recap of something we learnt in our JavaScript course, is the concept of && chaining. This can be used to short circuit to falsy values which is a feature we use for conditional rendering in React.

let person;

person = { name: { first: 'Jane', last: 'Doe' } };
console.log(person && person.name && person.name.first); // 'Jane'

person = null;
console.log(person && person.name && person.name.first); // null

let shouldDisplay;

shouldDisplay = true;
console.log(shouldDisplay && 'Display'); // 'Display'

shouldDisplay = false;
console.log(shouldDisplay && 'Display'); // false

React && chain on booleans

We can use && to conditionally render content in React.

  • When it is false, the chain short circuits to false and React renders nothing
  • When it is true, the chain continues to the item we want to render
App.tsx
import { useState } from "react";

export default function App() {
const [isShown, setIsShown] = useState(false);
const toggle = () => setIsShown((isShown) => !isShown);

return (
<div>
<button onClick={toggle}>Toggle</button>
{isShown && <p>Conditional Content</p>}
</div>
);
}

React && chain on nullish

For undefined and null (collectively called nullish as discussed in our JavaScript course), React also renders nothing and therefore we can use is similar to booleans

App.tsx
import { useState } from "react";

type User = { name: string } | null;

export default function App() {
const [user, setUser] = useState<User>(null);
const load = () => setUser({ name: "Jane" });
const clear = () => setUser(null);

return (
<>
<div>
<button onClick={load}>Load</button>
<button onClick={clear}>Clear</button>
</div>

{user && <p>{user.name}</p>}
</>
);
}

JavaScript !! operator

A quick recap of something we learnt in our JavaScript course, !! operator converts all Falsy values to boolean false

console.log(!!false); // false
console.log(!!null); // false
console.log(!!undefined); // false
console.log(!!''); // false
console.log(!!0); // false
console.log(!!NaN); // false

React && chain on numbers

We can convert falsy numbers to literal false by using !! before using them in conditional rendering with &&. This way all conditional rendering in React is done with && allowing us to write concise consistent code.

App.tsx
db.ts
import { useState } from "react";
import { db } from "./db";

export default function App() {
const [messages, setMessages] = useState<string[]>([]);
const addMessage = () => {
if (messages.length === db.length) return;
setMessages([...messages, db[messages.length]]);
}
const removeMessage = () =>
setMessages(messages.slice(0, messages.length - 1));

return (
<div className="App">
<div>
<button onClick={addMessage}>Add</button>
<button onClick={removeMessage}>Remove</button>
</div>
{!!messages.length && (
<ul>
{messages.map((message) => (
<li>{message}</li>
))}
</ul>
)}
</div>
);
}
javascript
typescript
react
playwright

Enjoy free content straight from your inbox 💌

No spam, unsubscribe at any time.

Transcript

00:00

A key objective of front-end frameworks is the ability to have dynamic rendering of UI animals. A key form of dynamic rendering is conditional rendering if something is either displayed or hidden based on a certain condition. Now I've seen some pretty silly mistakes when it comes to conditional rendering and react. So this lesson we will look at the core JavaScript principles that make conditional rendering possible, and then establish a simple guidebook that covers the good and the bad practices for conditional rendering and react. So let's go. Before we can truly understand conditional rendering and react, we need to understand the concept

00:32

of falsey values that exist within JavaScript. The complete list of falsey values consist of false null, undefined empty string, and the numbers zero and none. What this means is that when they're used within a conditional block, they behave essentially the same as a false, and we can prove this by simply running this application. And you can see that because all of these conditions are not true, we do not see any console log statements with this simple principle out of the way. Let's jump into a React application. Now, react has some special handling for these Falsey values

01:06

for the value false, no undefined and empty string react essentially renders nothing. And we can see that on the screen right now. However, for numeric values, which are zero, and Nan React does actually render them out, and this is not something that is by mistake. This is actually a valid choice by the React creators. So let's take a look at an example that demonstrates why the choice was made to always your numeric values, even though it might be zero. Consider the example of a very simple counter application that has the current count has increment

01:39

and decrement features for the count, and then we simply render out the plus and the minus buttons and the current count value. Now because React actually chooses to render out the numeric zero, we don't have to do any special handling over here, the numeric display of the count transitions smoothly from zero to positive values, and then if you decrement the count, it transitions smoothly back down from positive to zero to negative values. Now that we understand that React hides false values other than the numeric ones, the next concept that we need to cover in order for conditional rendering to make sense,

02:12

it's a JavaScript principle of an Channing. Consider the simple person variable, which contains an object that has a member name and then that member name is an object that contains the member first using the JavaScript Boo and and operator. If you create an ant chain between person, person name and person name first, JavaScript will keep evaluating the chain till it finds a false value, which in this case does not exist, and therefore we end up with person name first, which of course is Jane to further drive this point home. The JavaScript runtime first checks

02:45

that person is truthy, and yes it is. So it goes to person.name, which is also an object and truthy, and therefore it goes to person name first. However, if anything within the chain is falsely, then it is short circuited to that falsey value. For example, if a person is null, the JavaScript runtime is going to see that as a falsey and will not execute any of the other and operators. Now we can actually use and chaining for displaying certain items. The objective here is that if all of the conditions are true, we eventually resolve to the final object.

03:18

And in case any of those conditions are false, we get back that falsey value. And as we know that React does not render most falsey values. So we can actually use this knowledge of Falsey values and an chaining to do conditional rendering in React. As a basic demonstration, we utilize the use state hook to create a Boolean variable called is shown, and then a utility function. To toggle this between true and false, we create a button wide to the toggle function and then use an chaining to conditionally render a piece of content. Now, when this application starts, we have is shown pointing

03:53

to the value of a false. And as we know, this particular end chain will resolve to false. And as we also know, false is not something that is rendered by react. However, when we click the button to set the condition to true, this particular chain now resolves to the content which of course react renders to the screen. And of course we can click the button again to set the bullion to false, which of course results in the chain resolving to false, which of course does not get rendered to the screen. So chaining off of a bullion with an and is standard practice within react

04:25

to conditionally render a piece of content. But in addition to bullions, it is also conventional to use null and undefined. So let's take a look at another example. Here we have a simple type representing a user object. If the user is loaded, it'll be an object that contains the name property, otherwise it'll be. Now we have a state variable for a user within our application, which we initialize to null. We have a load function which loads chain, and then we have a clear function which sets it back to null. Within the ui, we have a button to load the user as well as a button to clear the user,

04:57

and then we can use our knowledge of conditional chaining to conditionally display a paragraph containing the username. Now, when user is null, this chain shortens to null, and as we know, react displays nothing. However, when we load the user, user becomes toothy and therefore it resolved through the paragraph containing user.name, which of course we see on screen. And of course, if we set the user back to null by example, clicking the clear button, that paragraph tag goes away. Now this method of chaining off of a bullion null and undefined is perfectly fine and conventional to do within react.

05:30

However, it is not safe to do so with numeric values. So let's take a look at an example that demonstrates an issue that can happen. If we do so, we are going to build a simple UI that displays a number of messages. We start with a single message, never gonna give you up. We create a utility to add a message which adds another message and remove a message which removes the last edit message. Within the ui, we have two simple buttons, one wide to add message and one wide to remove message. And then we check if there are any messages using messages length to conditionally render an unordered list

06:03

of all of the messages. Now we started off with a list containing a single item, and sure enough, we see an unordered list of that single message. And this does work as long as we have some messages and we can add as many as we want. But when we start to remove messages and we end up with zero messages, instead of not seeing any unordered list, we actually end up seeing the number zero. The reason, of course, is as we covered, it's a good thing that react renders numbers. So of course, as we see right now, it's a bad idea to use them for conditional chaining. Now, one quick fix that we can do is to use the ary operator

06:38

to map the falsey value of zero to the literal Now and now, if messages length is not zero, we get this unordered list. Otherwise, we get now and as we know, react will not render now. And with this simple change, we no longer get that ugly zero when there are no messages and removing all of the messages makes that list disappear. Now, I'm not a fan of using the turny operator for this particular purpose, and there are two key reasons why. The first reason is that this is verbose and not as elegant looking as and and. And then secondly, the intent

07:11

that we are only conditionally rendering something is not very clear. It feels like an if else where the else condition is just no. So it's a bit misleading in its intent and I would much rather prefer an upfront presentation of the fact that it is a simple if and I don't have to dig down to find the else condition. Fortunately, it's very easy to conveniently use conditional N chaining with all falsy values by combining it with one more JavaScript concept. Now, you might already be familiar with the fact that you can use the Knot operator to convert any falsey value to the literal true.

07:46

And similarly, if you use the Knot operator on the literal True, it converts it to the literal false. What this means is that we can actually use the Knot operator twice on any of the faulty values and be guaranteed that they will turn to the literal false lucky for us. We know that React does not render the literal false. So if you want to use any of the faulty values for a conditional chain, all that we need to do to be guaranteed that it doesn't get rendered in the Falsy case is to prefix it with Notnot. So for our particular use case,

08:19

we simply prefix messages length with Notnot and use our simple conditional chain. And we know that when it is going to be zero, it's not going to render anything. And when we do have messages, we get that unordered list. I'll wrap things up there. As always, thank you for joining me and I will see you in the next one.