Intro to Conditional Rendering in React
Learning Objectives
- Be able to describe why conditional rendering is important
- Use a ternary operator for conditional rendering
Conditional Rendering
We may want to render different things depending on state. For example, if a product is out of stock, we may want to hide the 'add to cart' button and instead put a message that says 'sorry out of stock'.
Since our dataset is simple and we don't have stock of items, what we can do is just put a simple message that states whether or not we are hiring.
Let's add to our constructor isHiring and set it to true
constructor(props) {
super(props);
this.state = {
products: products,
name: "",
price: 0,
description: "",
isHiring: true,
};
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
We'll use a ternary operator, which is just shorthand for an if/else statement
The following two examples are equivalent
const fact1 = true;
const fact2 = false;
let print;
if (fact1) {
print = "yes, it is true";
} else {
print = "no, that is false";
}
console.log(print);
let print = fact2 ? "yes, it is true" : "no, that is false";
console.log(print);
Now we can use this syntax to conditionally render the text of an h2 element:
<h1> Big Time Shopping </h1>;
{
this.state.isHiring ? (
<h2>Yes, we are hiring </h2>
) : (
<h2>Sorry, try again tomorrow</h2>
);
}
Extra, if there is time
Let's add a click event that toggles the value of our hiring.
We'll write a function
toggleHiring() {
this.setState({ isHiring: !this.state.isHiring });
}
and bind the value of this in the constructor
Finally, let's add a click event to our h1 (we could have made a button or chosen another element as well)
<h1 onClick={this.toggleHiring}> Big Time Shopping </h1>;
{
this.state.isHiring ? (
<h2>Yes, we are hiring </h2>
) : (
<h2>Sorry, try again tomorrow</h2>
);
}
More ways to conditionally render - caveat React updates often always check the date of articles - if something isn't working as expected, it may be that React was updated - these all should work with React 16.x
The full code for today's build:
class App extends React.Component {
constructor() {
super();
this.state = {
products: products,
name: "",
price: 0,
description: "",
isHiring: true,
};
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
this.toggleHiring = this.toggleHiring.bind(this);
}
handleChange(event) {
// this.state.value = event.target.value // NO!!!
this.setState({ [event.target.id]: event.target.value });
}
handleSubmit(event) {
event.preventDefault();
const newItem = {
name: this.state.name,
price: this.state.price,
description: this.state.description,
};
this.setState({
products: [...this.state.products, newItem],
name: "",
price: 0,
description: "",
});
}
toggleHiring() {
this.setState({ isHiring: !this.state.isHiring });
}
render() {
return (
<div>
<h1 onClick={this.toggleHiring}> Big Time Shopping </h1>
{this.state.isHiring ? (
<h2>Yes, we're hiring!</h2>
) : (
<h3>Sorry, try again tomorrow </h3>
)}
<form onSubmit={this.handleSubmit}>
<label htmlFor="name">Name</label>
<input
type="text"
value={this.state.name}
onChange={this.handleChange}
id="name"
/>
<br />
<label htmlFor="price">Price</label>
<input
type="number"
value={this.state.price}
onChange={this.handleChange}
id="price"
/>
<br />
<label htmlFor="description">Description</label>
<input
type="textarea"
value={this.state.description}
onChange={this.handleChange}
id="description"
/>
<br />
<input type="submit" />
</form>
<div>
<h2>Preview our new item</h2>
<h3>Name: {this.state.name}</h3>
<h4>Price: {this.state.price}</h4>
<h5>Description: {this.state.description}</h5>
</div>
<ul>
{this.state.products.map((product) => {
return (
<li>
{product.name} | {product.price} | {product.description}
</li>
);
})}
</ul>
</div>
);
}
}