When you’re building with the popular front-end library React, leveraging reusable components can make your job much easier. Components like tables and navbars are pretty much essentials—and you can add the ever-useful React checkbox to that list.
The React checkbox is a React component that implements a checkbox—that is, a widget that either displays a checked (true) or unchecked (false) state. (There’s also first-class support for an indeterminate state in a checkbox.) Checkboxes, alongside switches, are ideal UI components for displaying a boolean state.
With React’s component-based architecture, it’s typical for developers to build a React checkbox component that can be imported across the application. In this article, we’ll discuss how to build a React checkbox, its basic structure, and how to customize it.
In comparison to an ordinary HTML checkbox, a React checkbox is bound to a React state variable, which makes it easy to connect to the general logic of an application. Additionally, because mounting React components inside one another is made easy by the library, React checkboxes are very portable.
Independently, another benefit is that checkboxes are small and preserve space in the UI. They provide a clear indication of selected options. They may also automatically work with accessibility tools for blind or visually impaired users.
Building a React checkbox component is quite straightforward, but still includes all the rudimentary parts of any React component. Let’s go through each of them.
React’s useState
hook enables developers to initialize a React state variable within the component’s lifecycle. It also creates a function to safely set that variable. However, we will not include useState inside the React component—unlike Angular or Vue, React has an unidirectional data flow, so we’ll declare that outside of the component and pass it in as a prop. If we initialized the checkbox’s state from within the component, then the state would be inaccessible outside of it! That’s known as an uncontrolled element and isn’t ideal for this scenario.
1const Checkbox = (props) => {
2 return <></>
3}
4const App = () => {
5 const [val, setVal] = useState(false); //initializes checkbox to false
6 return <>
7 <Checkbox value={val} setValue={setVal}></Checkbox>
8 </>
9}
10
This code sets the initial code value of the checkbox to false.
Of course, we could do this over two files and import the Checkbox
into the App
component—but for the sake of brevity, we’ll keep them in the same file!
HTML has a native input element with a checkbox type. We’ll build our React checkbox component around this native element, directly interfacing with the HTML element’s native properties.
1const Checkbox = (props) => {
2 return <input type="checkbox" checked={props.val}/>
3}
4const App = () => {
5 const [val, setVal] = useState(false); //initializes checkbox to false
6 return <>
7 <Checkbox value={val} setValue={setVal}></Checkbox>
8 </>
9}
10
We’ll then use the general React event handler, onClick
, to alter the checkbox’s state, executed after any clicks. Because checkbox’s only flip state, we can easily set the correct value by inverting the checkbox’s present value.
1const Checkbox = (props) => {
2 return <input type="checkbox" checked={props.val} onClick={() => {props.setValue(!props.val)}}/>
3}
4const App = () => {
5 const [val, setVal] = useState(false); //initializes checkbox to false
6 return <>
7 <Checkbox value={val} setValue={setVal}></Checkbox>
8 </>
9}
10
The core benefit of this approach is it still uses HTML’s native checkbox input element, while simultaneously being apt for React applications.
There is an issue, however, with our current code. Sometimes, a user might change a checkbox’s value without clicking on it. Examples would be using the keyboard to focus on the checkbox and selecting it. Or, by using a screen reader.
Instead of using the onClick
prop, we want to use the onChange
prop to be more robust.
1const Checkbox = (props) => {
2 return <input type="checkbox" checked={props.val} onChange={() => {props.setValue(!props.val)}}/>
3}
4const App = () => {
5 const [val, setVal] = useState(false); //initializes checkbox to false
6 return <>
7 <Checkbox value={val} setValue={setVal}></Checkbox>
8 </>
9}
10
Of course, a floating checkbox isn’t too much help to the user. They also need to know what they are checking and un-checking. That’s where a checkbox label comes in handy.
A label is not just a text box that describes the checkbox. It’s also a clickable surface that changes the checkbox value. We can use HTML’s native label element to easily accomplish this. We’ll also set the text inside the label by using a prop so that the value could be set by the parent component!
1const Checkbox = (props) => {
2 return <label>
3 <input type="checkbox" checked={props.val} onChange={() => {props.setValue(!props.val)}}/>
4 {props.label}
5 </label>
6}
7const App = () => {
8 const [val, setVal] = useState(false); //initializes checkbox to false
9 const label = "My Checkbox!"
10 return <>
11 <Checkbox value={val} setValue={setVal} label={label}></Checkbox>
12 </>
13}
14
Sometimes, a checkbox might be deployed inside a form. If that’s the case, the checkbox needs a name so that it’s a named input inside of the form block. We can accomplish this by just making name another prop that is passed into the Checkbox component.
1const Checkbox = (props) => {
2 return <label>
3 <input type="checkbox" name={props.name} checked={props.val} onChange={() => {props.setValue(!props.val)}}/>
4 {props.label}
5 </label>
6}
7const App = () => {
8 const [val, setVal] = useState(false); //initializes checkbox to false
9 const label = "My Checkbox!"
10 return <>
11 <Checkbox value={val} setValue={setVal} label={label}></Checkbox>
12 </>
13}
14
Of course, almost all React apps are customized with personalized aesthetics. We can apply that same custom styling to our component. While this color scheme won’t necessarily match your application’s, it should illuminate how easy it is to add custom stylings.
Now, let’s break off Checkbox into its own file so that we can isolate our personalizations more cleanly.
1// checkbox.js
2import React from "react";
3import "./checkbox.css";
4
5const Checkbox = (props) => {
6 return (
7 <label className="checkbox">
8 <input
9 type="checkbox"
10 name={props.name}
11 checked={props.val}
12 onChange={() => {
13 props.setValue(!props.val);
14 }}
15 />
16 {props.label}
17 </label>
18 );
19};
20
21export default Checkbox;
22
Now we can create a CSS file that will be imported into our component.
1/* checkbox.css */
2
3label.checkbox {
4 color: #ddd;
5 display: flex;
6 align-items: center;
7 justify-content: left;
8 width: 300px;
9 gap: 4px;
10}
11
12label.checkbox > input {
13 outline: none;
14 height: 20px;
15 border-radius: 5px;
16}
17
Of course, these styles should follow how CSS is configured in an application as well as the application’s overall style guide.
We can now import that Checkbox into the original App.js.
1// App.js
2
3import React from "react";
4
5const App = () => {
6 const [val, setVal] = useState(false); //initializes checkbox to false
7 const label = "My Checkbox!"
8 return <>
9 <Checkbox value={val} setValue={setVal} label={label}></Checkbox>
10 </>
11}
12
While a standardized checkbox is what’s in scope for today’s tutorial, there are additional optional props you could consider. These include:
- The ability to personalize the checkbox color or choose between preset color themes
- A boolean to gray out / disable the checkbox
Of course, it only makes sense to add these features if they are going to be actually invoked in the application.
In this article, we explored how to build a configurable and personalized React checkbox component. The component has a configurable label and can dynamically invoke a mutation function. With React’s component-based structure, the component can easily be reused throughout the application.
The best React component library is in Retool. Grab a checkbox component and get building.
Reader