Conditional rendering in React isn’t difficult. In JSX - the syntax extension used for React - you can use plain JavaScript which includes if else statements, ternary operators, switch case statements, and much more. In a conditional render, a React component decides based on one or several conditions which DOM elements it will return. For instance, based on some logic it can either return a list of items or a text that says “Sorry, the list is empty”. When a component has a conditional rendering, the appearance of the rendered component differs based on the condition.
The most basic conditional rendering logic in React is done with a single if statement. Imagine you don’t want to render something in your React component, because it doesn’t have the necessary React props available. For instance, a List component in React shouldn’t render the list HTML elements in a view if there is no list of items in the first place. You can use a plain JavaScript if statement to return earlier (guard pattern):
const users = [
{ id: '1', firstName: 'Robin', lastName: 'Wieruch' },
{ id: '2', firstName: 'Dennis', lastName: 'Wieruch' },
];
function App() {
return (
<div>
<h1>Hello Conditional Rendering</h1>
<List list={users} />
</div>
);
}
function List({ list }) {
if (!list) {
return null;
}
return (
<ul>
{list.map(item => (
<Item key={item.id} item={item} />
))}
</ul>
);
}
function Item({ item }) {
return (
<li>
{item.firstName} {item.lastName}
</li>
);
}
In React, transforming arrays into lists of elements is nearly identical to Javascript way.
You can build collections of elements and include them in JSX using curly braces {}.
Below, we loop through the numbers array using the JavaScript map() function. We return a <li> element for each item. Finally, we assign the resulting array of elements to listItems:
const numbers = [1, 2, 3, 4, 5];
const listItems = numbers.map((number) =>
<li>{number}</li>
);
We include the entire listItems array inside a <ul> element, and render it to the DOM:
ReactDOM.render(
<ul>{listItems}</ul>,
document.getElementById('root')
);
Keys help React identify which items have changed, are added, or are removed. Keys should be given to the elements inside the array to give the elements a stable identity:
const numbers = [1, 2, 3, 4, 5];
const listItems = numbers.map((number) =>
<li key={number.toString()}>
{number}
</li>
);
The best way to pick a key is to use a string that uniquely identifies a list item among its siblings. Most often you would use IDs from your data as keys:
const todoItems = todos.map((todo) =>
<li key={todo.id}>
{todo.text}
</li>
);
When you don’t have stable IDs for rendered items, you may use the item index as a key as a last resort:
const todoItems = todos.map((todo, index) =>
// Only do this if items have no stable IDs
<li key={index}>
{todo.text}
</li>
);
HTML form elements work a little bit differently from other DOM elements in React, because form elements naturally keep some internal state. For example, this form in plain HTML accepts a single name:
<form>
<label>
Name:
<input type="text" name="name" />
</label>
<input type="submit" value="Submit" />
</form>
This form has the default HTML form behavior of browsing to a new page when the user submits the form. If you want this behavior in React, it just works. But in most cases, it’s convenient to have a JavaScript function that handles the submission of the form and has access to the data that the user entered into the form. The standard way to achieve this is with a technique called “controlled components”.
In HTML, form elements such as < input>, < textarea>, and < select> typically maintain their own state and update it based on user input. In React, mutable state is typically kept in the state property of components, and only updated with setState().
We can combine the two by making the React state be the “single source of truth”. Then the React component that renders a form also controls what happens in that form on subsequent user input. An input form element whose value is controlled by React in this way is called a “controlled component”.
For example, if we want to make the previous example log the name when it is submitted, we can write the form as a controlled component:
class NameForm extends React.Component {
constructor(props) {
super(props);
this.state = {value: ''};
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleChange(event) {
this.setState({value: event.target.value});
}
handleSubmit(event) {
alert('A name was submitted: ' + this.state.value);
event.preventDefault();
}
render() {
return (
<form onSubmit={this.handleSubmit}>
<label>
Name:
<input type="text" value={this.state.value} onChange={this.handleChange} />
</label>
<input type="submit" value="Submit" />
</form>
);
}
}