Conditional Rendering
Composi allows you to conditionally render the elements that a component produces.
You can use JavaScript operators like if
and else
, or the ternary
operator when making decisions about what markup a component should create.
As an example of conditional rendering, lets use a situation where depending on whether the user is logged in or not, we render two different sub-components. Here's the two possible components:
function UserGreeting(props) {
return <h1>Welcome back!</h1>
}
function GuestGreeting(props) {
return <h1>Please sign in.</h1>
}
Now lets create a component that returns these two sub-components and based on the loggedon condition, returns one or the other. Try opening the Codepen and changing the value of isLoggedIn
to false.
See the Pen Composi Tuts - conditional-rendering-1 by Robert Biggs (@rbiggs) on CodePen.
Conditional Element Variables
You can use a variable to conditionally store an element and then return that in the render
function. In the next example we are going to combine the Greeting element from above with conditional rendering of buttons for a login. When the user clicks the button, the logged in status will change visibly on the page. Notice how we store the button in a variable and out put it with {button}
in the component's render
function, keeping it very clean:
See the Pen Composi Tuts - conditional-rendering-2 by Robert Biggs (@rbiggs) on CodePen.
Using the Logical && Operator
You can also use the JavaScript logical && operator for conditional situations. In the above example we can simplify the handleEvent
method by using the && operator as a condition check:
// Original with if statement:
handleEvent(e) {
if (e.target.class === 'login') {
this.handleLoginClick(e)
} else if (e.target.class === 'logout') {
this.handleLogoutClick(e)
}
}
// New version using &&
handleEvent(e) {
e.target.class === 'login' && this.handleLoginClick(e)
e.target.class === 'logout'&& this.handleLogoutClick(e)
}
When you see an expression like this, read it like this: When e.target.class equals "login", execute this.handleLoginClick(e)". Basically, the first part is a check, if it is true then the && will execute whatever follows.
We can also use the && operator to conditionally render an element. If the first statement is true, then return the element to render. In the next example, the element will render only if the number of messages is greater than 0:
See the Pen Composi Tuts - conditional-rendering-3 by Robert Biggs (@rbiggs) on CodePen.
Inline Ternary Operator
Another way to render things conditionally is to use the JavaScript ternary operator: condition ? true : false
. The ternary operator is great for reducing conditional if/else
statements to a single line. However, creating nested ternary statements results in difficult to read code, so avoid doing that.
You can use the ternary operator for simple decisions about what to print out based on a condition:
render() {
const isLoggedIn = this.state.isLoggedIn
return (
<div>
The user is <b>{isLoggedIn ? 'currently' : 'not'}</b> logged in.
</div>
)
}
As you can see, using the ternary operator makes the test clean and easy to reason about.
In our previous example we had a render
function like this:
render() {
const isLoggedIn = this.state.isLoggedIn
if (isLoggedIn) {
button = <LogoutButton />
} else {
button = <LoginButton />
}
return (
<div>
<Greeting isLoggedIn={isLoggedIn} />
{button}
</div>
)
}
Using the ternary operator, we can simplify the logic to this:
render() {
const isLoggedIn = this.state.isLoggedIn;
return (
<div>
{ isLoggedIn ? <LogoutButton /> : <LoginButton /> }
</div>
);
}
Prevent an Component from Rendering
Sometimes you want to not render a component from rendering. The best way to do that is to test for a condition and have the render
function return null
. Notice how we do that with the WarningBanner
component below:
See the Pen Composi Tuts - conditional-rendering-5 by Robert Biggs (@rbiggs) on CodePen.
Because WarningBanner
is a child component to Page
, when WarningBanner
returns null, that only affects its output. It will not affect the output of the button nor the lifecycle methods and events.