This tutorial covers React 15 and is now out of date.
The good news is: Checkboxes in React 16 is available!
How do you use checkboxes in React.js? We've learnt about radio buttons in this tutorial, but what about checkboxes - do you use them differently in React?
The short answer is: yes.
Let me demonstrate how to use checkboxes with the help of a simple React application:
You can find the full source code in this GitHub repository.
Our application is going to render a list of checkboxes with labels and a Save
button. We can toggle checkboxes and click Save
button. We will then see in the Developer Tools Console log messages that tell us which checkboxes were checked:
Our application will be made of two React components:
Application
Checkbox
Application
component is a container component - it encapsulates our entire React.js application, and renders three instances of Checkbox
component and a Save
button. Application
component also logs into the Developer Tools Console which checkboxes were checked when users click the Save
button.
Checkbox
component renders a checkbox with a label.
Let's create our Application
component first:
First, let's focus on its render
function:
We see three div
elements with class names that you might recognize if you're familiar with Bootstrap. Bootstrap helps us create layout for our page.
Now let's focus on the form
element:
Inside of our form
element we call this.createCheckboxes
function that creates three instances of a Checkbox
component. We'll see how exactly it does that in a moment. It's important to recognise that here we're creating our instances of a Checkbox
component dynamically. If you're not familiar with this approach, then please read this tutorial first.
We then create a button element of type submit
which will submit our form when user clicks on it, we're telling React to call this.handleFormSubmit
function when this happens: <form onSubmit={this.handleFormSubmit}>
.
Let's take a look at how exactly we're creating our instances of Checkbox
component dynamically. Here is our createCheckboxes
function:
It iterates over items
array and calls this.createCheckbox
function for each item in that array. Where is items
array coming from and what is it for?
In our Application.js
file before declaring our Application
component, we create items
constant that references an array of three items:
['One', 'Two', 'Three']
- these are labels for our checkboxes. This array represents data that will dictate how many checkboxes we need to render and what their labels will be. For the purpose of this tutorial, we declare this data in our React component file, but in a real world web application this data can be received from a server or imported from another file.
Now we know that createCheckboxes
function calls this.createCheckbox
function for each label in items
array. createCheckboxes
function also returns an array of three instances of Checkbox
component. That's because we call this.createCheckbox
three times and each time it creates and returns an individual 'Checkbox' component instance:
Each Checkbox
component instance gets three properties:
label
- the text that you see rendered next to a checkbox. This value is coming from our items
array.handleCheckboxChange
- a reference to this.toggleCheckbox
function. Every time user checks/unchecks a checkbox React calls this.toggleCheckbox
function. We'll see what it does in a moment.key
- as you already know, each dynamically created React component instance needs a key
property that React uses to uniquely identify that instance.Now we understand how we create and render three checkboxes in our application. What happens when user checks/unchecks our checkbox? As you will see later - every time user change checkbox's state - our this.toggleCheckbox
is called.
Let's take a look at that toggleCheckbox
function:
It gets a label
parameter that represents which checkbox is being toggled. Now what exactly toggleCheckbox
function does with a label
?
It's a good time to zoom out for a second and talk about how our application works. There are a couple of questions we need to ask:
Each checkbox has two states: checked and unchecked. Which React component is responsible for managing that state?
How do we know which checkboxes are checked at any given moment in time?
We want to keep our application as simple as possible, so a simple answer for our first question is: let each Checkbox
component instance maintain it's own state. Meaning: each Checkbox
component instance is responsible for managing it's own state and knowing when it's checked or unchecked.
That's the key point: our Application
component is not responsible for managing Checkbox
component instance state and hence it doesn't know anything about it. The advantage of this approach is that now our Application
component can create as many instances of a Checkbox
component as we need and it doesn't need to deal with managing the state of each Checkbox
instance. In addition this solution makes our Checkbox
component more reusable as it doesn't depend on a parent component.
This sounds fantastic, but coming back to our second question: how do we know which checkboxes are checked in our Application
component? This question highlights the disadvantage of our approach, because as I've mentioned earlier, our Application
component knows nothing about state of each instance of a Checkbox
component.
Luckily, there is no need for our Application
component to know the state of each instance of a Checkbox
component at any given time. All it needs to know is: which checkboxes are selected at any given time.
Should we store that information in Application
component's state? Should we make our Application
component stateful?
No. Remember in React you want to keep as little information in component's state as possible. And this should come naturally to you when you start thinking about it this way: does this information affects what my component is rendering? In other words, if that information changes - do I want React to rerender my component? If the answer is "no" - don't store it in component's state. If the answer is "yes", then that information represents your component's state and it should be stored in your component's state.
In the case of our Application
component - when user checks or unchecks any checkbox that we render - do we need to rerender our Application
component? The answer is clearly no. Therefore, we don't want to store a list of checked checkboxes in Application
component's state.
Ok, if not in the component's state, then where? In a property that we can set on the component's class.
Let's set a property on the component's class that will store information about which checkboxes are checked. The next question that we should ask ourselves is: which data structure should I choose for storing that information?
What are the requirements for our perfect data structure?
That sounds like a description of a data structure that you might know about: Set.
Sets are not supported in ES5 version of JavaScript, but luckily, we're using ES2015 version of JavaScript where Sets are supported.
Now we know that we want to create a new Set and assign it to Application
's component specification object.
The next question we need to answer is: when should we create our empty Set? That will depend on whether we want our Set to be created before or after the Application
component is rendered.
The answer is: we want our Set to be created right before we mount our Application
component:
If you're not familiar with componentDidMount
method or any other React component lifecycle methods, then please read this tutorial first.
this.selectedCheckboxes = new Set();
creates a new selectedCheckboxes
property on component specification object and assigns a new set to it.
Now we have an empty set created right before our Application
component is rendered. Then, when user checks/unchecks our checkboxes React will call toggleCheckbox
function:
That function will reference our set and check if a specific checkbox label is in that set:
If the label is already in our set then we delete from the set:
Otherwise, we add it to our set:
And that's how our Application
component is going to know which checkboxes are checked at any given moment in time. If the label in the set - it's checked; if not - it's unchecked.
What happens when the user clicks Save
button? Our form is submitted and our handleFormSubmit
function is called by React:
Let's take a look at handleFormSubmit
function:
First it prevents the default behavior of a form's submit event:
And then:
It uses for... of
statement to iterate through our this.selectedCheckboxes
set and log every item from that set. Which effectively prints the label of every checked checkbox.
for... of
statement is available to us in JavaScript version ES2015.
Now you know how what our Application
component does and how it works.
Next let's take a look at our Checkbox
component:
Our Checkbox
component is a stateful component because it needs to know whether a checkbox element should be rendered as checked or unchecked.
We'll use class property state
to set the initial state of our Checkbox
component:
The state of our component is represented by isChecked
property. By the default its value is set to false
because initially we want every checkbox to render as unchecked.
Let's see what our Checkbox
component renders:
It renders div
element with a Bootstrap class name that we use for styling. Inside of it we have label
element with two children: 1) input
element and 2) label text.
The input
element renders the checkbox. It has 4 properties:
type
- the type of input: checkbox
in our case.value
- the value of input: which is a label name passed as property from a parent Application
component.checked
- whether it's checked or not. The value comes from component's state property isChecked
.onChange
- change
event handler: this.toggleCheckboxChange
function will be called when user checks or unchecks a checkbox.The label text is coming from a property label
that is passed from a parent Application
component. It will be either One
, Two
or Three
.
Now if you read this tutorial, you will recognise that our input
element is a controlled component because we "control" the value
property by providing our own value that comes from this.props.label
. If you're not sure about the difference between controlled components and uncontrolled components, then I recommend you read this tutorial.
What happens when the user toggles our checkbox? this.toggleCheckboxChange
function is called:
It changes Checkbox
component's state. It set's isChecked
's value to the opposite of it's current value and it calls handleCheckboxChange
function which is passed to Checkbox
component as a property by it's parent Application
component:
This function call will trigger toggleCheckbox
function in Application
component that will add or delete the label name that we're passing as an argument via this.props.label
from the set.
That's how our Application
component will always know which checkboxes are selected at any given moment in time.
And now you know how to use checkboxes in React.js!
Notice that this solution works great for our specific needs. If you have different requirements you might need to think of a different way of creating checkboxes. For example, how do you implement a button that checks all checkboxes? I'll leave it for you to figure it out as a challenge! And if you do figure it out - please propose your tutorial for this website!
Thank you for reading this React tutorial!
Please take a look at the complete source code on GitHub and the live version of our app.
I hope you've enjoyed this tutorial and I would love to hear your feedback in the comments. You can get in touch with me via Twitter and email.
P.S. I've also written React.js Essentials book and I teach people React.js and JavaScript!