Conditional Rendering Syntax in React
By: Dave Frame
Tags: React, JavaScript, Ternary Operator, Conditional Rendering

Why We Can’t Use If-Else and How the Ternary Operator can Help

One of the great strengths of the React.js framework is its modular design philosophy. When we break our page into modular components, we also gain a lot of control over how, where, when, and whether a component is rendered. The latter question, the “whether,” seems especially important in an interactive web app. Without it, we wouldn’t have things like modals, dropdown lists, and accordion menus. These are all examples of conditional rendering.

The word “conditional” might tip us off here that we’re going to be dealing with, well, conditionals (i.e., if, else if, else). If some condition is met, render one component, else (if the condition isn’t met), render another one. While, logically, this is true, syntactically, it won’t be so simple. Here’s an example:

Here we have a template to create a flashcard for studying. We want to start with a term, and render the definition after we click on the card. The FlashCard component also has a state of “clicked” initialized to false. This state is how we can keep track of our clicks.

NOTE: In a full-size React app, you might choose to keep track of your clicks via object mutation (i.e., adding a “clicked” key to the object when storing it in state in a parent component), or via props from a parent component. I’m using state in this example to limit our scope to a single component/file.

React uses JSX, which allows us to write our code using HTML-like syntax, making it easy to visualize how it will render. The above code looks like we’re using an HTML div tag. JSX gives us that HTML feel, while also allowing us to implement JavaScript inside those curly braces. This is presumably where our conditional logic would belong. So, what if we just use a standard conditional statement, like so:

The weird syntax highlighting might tip us off, but this code won’t run. The syntax seems valid enough, HTML elements aside. But we’ll get a message saying “unexpected token,” pointing us to our if statement.

You might know all this already. The React documentation prepares us for this outcome. Per the docs:

if-else statements don’t work inside JSX. This is because JSX is just syntactic sugar for function calls and object construction. Take this basic example:

// This JSX:

ReactDOM.render(<div id="msg">Hello World!</div>, mountNode); // Is transformed to this JS:

ReactDOM.render(React.createElement("div", {id:"msg"}, "Hello World!"), mountNode);

This means that if statements don’t fit in…

This is a great start. JSX is syntactic sugar. It is HTML-like, but it isn’t HTML. When we used those div tags, we were really just calling React’s createElement function. Unfortunately, if you’re relatively new to JavaScript, as I am, this might not do anything to clear up the question of why if statements “don’t fit in.” Especially after we find out that this isn’t the end of conditional rendering. All we have to do is refactor a little bit.

This code compiles no problem. What gives? Why can we use the ternary operator and not an if-else statement? Isn’t the ternary operator just an if-else statement itself? The answer, apparently, is: sort of, but not really!

We got more of a clue from those React docs than it seems on the first read. “If statements don’t fit…”

Statements vs. Expressions

As it turns out, while the ternary (or conditional) operator does help us achieve the same functionality as if-else statements with fewer lines of code, there is an important distinction between the two. The standard if-else is a statement, whereas the ternary operator is an expression.

An expression is any unit of code that evaluates to a value. 2 + 2 (arithmetic expression) is an expression. So is ‘hello world’ (string expression), 3 < 5 (logical expression), and sum = 4 (assignment expression). Since expressions evaluate to a value, we can use them anywhere a value is expected. This includes as an argument for a function invocation.

By contrast, statements are instructions. They may contain expressions, but they are not required to return a value. A typical example might be variable declaration. If you type let sum = 4 into your browser's console, you get back "undefined." This is in contrast to our assignment expression sum = 4 which will return "4." Really, let sum = 4 is just telling the console "create a variable." It isn't an expression to be evaluated; it's an instruction to be executed. Because we aren't guaranteed a return value, we can't use statements in place of values. Thus we can't put statements in our function arguments.

Conclusion

So, JSX is syntactic sugar. When we write JSX, it gets changed into a standard JS function invocation. This limits us from using statements in our JSX (as an argument for the createElement function). However, we don’t have to use the ternary operator. We can handle any expression. This includes function calls and other logical operators. If we really wanted to use an if-else statement, all we’d have to do is wrap it in a function and pass the function as an argument. Also, the ternary vs. if-else debate assumes we are deciding between two elements to display. If we were only interested in rendering or not rendering a single element, we might use the && logical operator. You can find a fairly exhaustive list of alternatives for conditional rendering here.

Resources: