---
tags: ironhack, lecture,
---
<style>
.markdown-body img[src$=".png"] {background-color:transparent;}
.alert-info.lecture,
.alert-success.lecture,
.alert-warning.lecture,
.alert-danger.lecture {
box-shadow:0 0 0 .5em rgba(64, 96, 85, 0.4); margin-top:20px;margin-bottom:20px;
position:relative;
ddisplay:none;
}
.alert-info.lecture:before,
.alert-success.lecture:before,
.alert-warning.lecture:before,
.alert-danger.lecture:before {
content:"👨🏫\A"; white-space:pre-line;
display:block;margin-bottom:.5em;
/*position:absolute; right:0; top:0;
margin:3px;margin-right:7px;*/
}
b {
--color:yellow;
font-weight:500;
background:var(--color); box-shadow:0 0 0 .35em var(--color),0 0 0 .35em;
}
.skip {
opacity:.4;
}
</style>

# React | Conditional Rendering
## Learning Goals
After this lesson you will be able to:
- Render component according to conditions
- Understand how to implement conditional rendering in React
- Implement **ternary operator** for conditional render
## Introduction
In React, you can create distinct components that encapsulate the behavior you need. Then, you can render only some of them, depending on the state of your application.
Conditional rendering in React works the same way conditions work in JavaScript. Use JavaScript operators like if or the conditional operator to create elements representing the current state, and let React update the UI to match them.
Example:
```jsx
if (true) {
return <SomeComponentGoesHere/>
} else {
return <OtherComponentGoesHere/>
}
```
While using an if statement is a fine way to conditionally render a component, sometimes you might want to use a shorter syntax. There are a few ways to inline conditions in JSX. One way to go about this is using **ternary operator**: `condition ? true : false`.
### Simple conditional rendering an object
Let's keep working within our small project and our next step is to slightly update our `movies` array in the state of `<DynamicMoviesList />` component:
:::info lecture
Reprise du projet `my-new-app` et modification des datas pour **ajouter les champs `hasOscars` et `IMDbRating`** aux objects movies :
:::
```jsx
// components/dynamicListsDemo/DynamicMoviesList.js
...
class DynamicMoviesList extends Component {
constructor(props) {
super(props);
this.state = {
movies: [
{ id: "fUbJPciPq", title: "The Godfather", director: "Francis Coppola", hasOscars: true, IMDbRating: 9.2 },
{ id: "EXN9npPlo", title: "Star Wars", director: "Rian Johnson" , hasOscars: true, IMDbRating: 8.7 },
{ id: "lecqGHnAb", title: "The Shawshank Redemption", director: "Frank Darabont", hasOscars: false, IMDbRating: 9.3 }
]
}
}
...
}
```
Nothing's still changed in our app, we still can see the same result. So let's make some changes in our `<ImprovedCard />` component. We can implement inline ternary operator for more straightforward logic:
:::info lecture
Nous allons maintenant, **grâce à l'opérateur ternaire**, afficher si oui ou non un film a reçu un oscar grâce à la nouvelle donnée `hasOscars`
:::
```jsx
// components/dynamicListsDemo/ImprovedCard.js
import React from 'react';
const ImprovedCard = (props) => {
return (
<div className="movies-list-item">
<h2>{props.title}</h2>
<p>Director: {props.director}</p>
{
props.hasOscars ?
<p>Got the Oscar Award! 😉 </p>
:
<p>Great movie but no Oscars! 😔 </p>
}
<button onClick={props.clickToDelete}>Delete</button>
</div>
)
};
export default ImprovedCard;
```
:::info lecture
Plus simple que de définir une fonction utilitaire :
```jsx
function displayOscars(hasOscars) {
if (hasOscars) {
return <p>Got the Oscar Award! 😉 </p>;
} else {
return <p>Great movie but no Oscars! 😔 </p>;
}
}
```
appelée par:
```jsx
...
{displayOscars(props.hasOscars)}
```
:::
:::info lecture
On remarque aussi la présence des `{}` autour :
```jsx
{
props.hasOscars ?
// OUI
:
// NON
}
```
:::
:::info lecture
On oublie pas non plus que la valeur retournée doit être dans une balise englobante :
```jsx
return (
...
{
props.hasOscars ?
<div>
<p>Got the Oscar Award!</p>
<p>🎉 Samba!</p>
</div>
:
<p>Pas d'oscar 😭</p>
}
...
);
```
:::
**Even simpler logic**
Let's use a more *outstanding approach* that has better use of JS grammar. You may embed any expressions in JSX by wrapping them in curly braces. This includes the JavaScript logical `&&` operator. Let's update code in our *ImprovedCard.js*:
:::info lecture
Opérateurs booléens: `&&`, `||`
:::
```jsx
// components/dynamicListsDemo/ImprovedCard.js
import React from 'react';
const ImprovedCard = (props) => {
return (
<div className="movies-list-item">
<h2>{props.title}</h2>
<p>Director: {props.director}</p>
{ props.hasOscars && <p>Got the Oscar Award! 😉 </p> }
{ !props.hasOscars && <p>Great movie but no Oscars! 😔 </p> }
<button onClick={props.clickToDelete}>Delete</button>
</div>
)
};
export default ImprovedCard;
```
It works because in JavaScript, **true && expression always evaluates to expression**, and **false && expression always evaluates to false**.
Therefore, if the condition is true, the element right after `&&` will appear in the output. If it is false, React will ignore and skip it.
:::info lecture
Si plus complexe qu'un simple `if/else` => recours aux variables avant le `return`
:::
If the conditional rendering logic is a more complex, which is not in our case but we will use this example to demonstrate the approach, it is better to extract condition outside JSX:
```jsx
// components/dynamicListsDemo/ImprovedCard.js
import React from 'react';
const ImprovedCard = (props) => {
let awardText;
if(props.hasOscars){
if(props.IMDbRating >= 9){
awardText = <p> WOW! Oscar Award and IMDb rating {props.IMDbRating}! </p>
} else if(props.IMDbRating >= 7){
awardText = <p> Got the Oscar Award and has IMDb rating {props.IMDbRating}, not bad at all! </p>
}
} else {
awardText = <p> Great movie but no Oscars! Has IMDb rating {props.IMDbRating}. </p>
}
return (
<div className="movies-list-item">
<h2>{props.title}</h2>
<p>Director: {props.director}</p>
{awardText}
<button onClick={props.clickToDelete}>Delete</button>
</div>
)
};
export default ImprovedCard;
```
### State conditional rendering
The other way of displaying the movies in the `<DynamicMoviesList />` component could be something like this:
:::info lecture
Nous allons maintenant filtrer la liste des films, en fonction de s'ils ont ou non remportés un oscar :
:::
```jsx=
// components/dynamicListsDemo/DynamicMoviesList.js
...
class DynamicMoviesList extends Component {
constructor(props) {
super(props);
this.state = {
movies: [
{ id: "fUbJPciPq", title: "The Godfather", director: "Francis Coppola", hasOscars: true, IMDbRating: 9.2 },
{ id: "EXN9npPlo", title: "Star Wars", director: "Rian Johnson" , hasOscars: true, IMDbRating: 8.7 },
{ id: "lecqGHnAb", title: "The Shawshank Redemption", director: "Frank Darabont", hasOscars: false, IMDbRating: 9.3 }
],
showOscarAwarded: false // 👈
}
}
// 👇
toggleMovies = () => {
this.setState({ showOscarAwarded: !this.state.showOscarAwarded })
}
...
render() {
console.log(this.state.movies);
// 👇 Filter movies based on `this.props.showOscarAwarded` value
const {showOscarAwarded} = this.state;
const filteredMovies = this.state.movies.filter(theMovie => theMovie.hasOscars === showOscarAwarded);
return (
<div>
{/* 👇 Display filtered movies */}
{filteredMovies.map(=item => {
return <ImprovedCard key={item.id} {...item} clickToDelete={() => this.deleteMovieHandler(item.id)} />
})}
{/* 👇 Toggle */}
<button onClick={() => this.toggleMovies() }>
{showOscarAwarded ? 'Hide Oscar Awarded' : 'Show Oscar Awarded'}
</button>
</div>
);
}
}
```
:::info lecture
Nous affichons maintenant une liste de films, filtrés avec la valeur de l'état `this.props.showOscarAwarded`. La liste filtrée est "calculée" à chaque `render()`
:::
:::info lecture
Nous ré-initialisons la liste de films à chaque appel à `this.toggleMovies`
:::
:::info lecture
Notons aussi l'utilisation de l'opérateur ternaire ligne 41.
:::
### Practice
Take a look of the following example and play around with it:
<iframe height='265' scrolling='no' title='Preventing Component Rendering' src='//codepen.io/ironhack/embed/GBwKdo/?height=265&theme-id=0&default-tab=js,result&embed-version=2' frameborder='no' allowtransparency='true' allowfullscreen='true' style='width: 100%;'>See the Pen <a href='https://codepen.io/ironhack/pen/GBwKdo/'>Preventing Component Rendering</a> by Ironhack (<a href='https://codepen.io/ironhack'>@ironhack</a>) on <a href='https://codepen.io'>CodePen</a>.
</iframe>
:::info lecture
Ma version : https://codepen.io/abernier/pen/EMaYob?editors=1010
:::
## Summary
Conditional rendering is one of the most common ways to show/hide components in React apps. When developing your applications you will find situations where you want to display specific components depending on some variables, so be sure to understand how to implement the conditional rendering.
## Extra Resources
- [React Conditional Rendering](https://reactjs.org/docs/conditional-rendering.html)