џџHow to build a React switch | Retool Blog
Skip to main content

How to build a React switch

Blog article hero image
Mathew Pregasen
Mathew Pregasen
Guest Writer

Sometimes, you just need to switch things up.

Say, from т€œonт€ to т€œoff.т€ т€œLight modeт€ to т€œdark mode.т€ т€œAvailableт€ to т€œunavailable.т€

The ever-toggleable React switch component is just the ticket to make that possible. And with Reactт€™s component-based architecture, itт€™s common for developers to build a React switch component that they can import across an application.

Letт€™s explore how to build a React switch from scratch, the basic component structure, and how to customize a switch component with consideration toward ease of use.

First things first, what is a React switch component?

A switch is a common UI component that displays and toggles a state between two possible values. It typically represents a boolean, like т€œTrue or Falseт€ and т€œYes or Noт€. Additionally, under WAI-ARIA guidelines, thereт€™s a third mixed state reflecting a partially checked checkbox. (Todayт€™s example wonт€™t cover that, but we encourage you to center accessibility and get familiar with those guidelines!)

Also, to be super clear, the switch component weт€™re working with today is not a JavaScript switch statementт€”which is a totally different native logic statement.

Why should you use a React switch component?

Building a React switch component makes it easy for a user to handle booleans. With a simple import statement, developers could drop-in a component that has all the bells and whistles to handle toggle events.

Designing the component

There are certain design considerations to keep in mind when building a robust React switch component. Ideally, the component needs to match your app or companyт€™s design language without overcomplicating the switchт€™s logic or functionality.

Defining the basic component structure

The most simple React switch component needs two core input props:

  • A value variable that defines the switchт€™s state. This variable could be a number (e.g., 0 and 1) or string (e.g., т€œonт€ and т€œoffт€). However, itт€™s cleanest to use the native boolean type (e.g., true and false).
  • A onChange function that can be invoked to mutate the switchт€™s value. Itт€™s important that this be a prop given Reactт€™s unidirectional data flowт€”the value shouldnт€™t ever be modified directly.

Additionally, a React switch requires a very basic HTML structure. Foremost, it needs a main container div whose background represents the switchт€™s state. It also needs a togglable switch elementт€”a т€œhandleт€ or т€œknobт€т€”that moves upon click.

Technically, this can be accomplished with just a single div element in addition to its ::before or ::after properties being repurposed for the handle, but given that React is an abstraction layer that simplifies re-using code, such over-the-top conciseness isnт€™t generally necessary.

Supporting a color theme

In this example, weт€™ll use four color statesт€”the color of the switchт€™s background and the switchт€™s handle as well as the same when the switch is enabled.

Some switches might bake these colors into the component if the switch is to appear the same throughout the application. But accepting additional props to alter these colors can be a nice optional feature, especially if the switch is used in alternative contexts (e.g., a negative context when the switch is disabling a feature).

Setting valid colors for the toggle switches

Itт€™s important that the toggle switch communicates to the user when it is on versus off. In some cases, we might want to make these colors props so that the component can switch colors in various settings. (For instance, a switch disabling something might be red when on.)

Thankfully, React makes such customization easy. We just have to include two additional propsт€”an `checkedColor` prop and an `uncheckedColor` prop where the valid colors are ingested into the component. Another set of two propsт€”checkedHandleColor and uncheckedHandleColorт€”are fantastic for altering the handle or knobт€™s color theme.

Considering user interactions with the React switch

There are various user interactions to consider when building a React switch component. These include handling toggle events. Three common props are onToggle, onTrue, and onFalse to fire during the respective events.

These props enable the React switch to trigger logic whenever a user interacts with it.

Including a hidden native checkbox input

Finally, itт€™s important that the React switch contains a native input checkbox element thatт€™s hidden with the correct data binding to the componentт€™s props. This helps keep the underlying form accessible by using native form fields that are cleanly defined to the DOM. Itт€™s quite easy to do this with a checkboxт€™s native props.

Coding the component

Weт€™ll progressively build out the component, slowly adding more robust functionality to address the previous concerns.

Starting with a base component

Given a React switch componentт€™s functionality is rather simple, weт€™ll start out with a simple functional component. To begin, weт€™ll populate it with a container div and an empty div thatт€™ll become our handle.

1
2
3
4
5
6
7
8
9
10
11
12
import React from "react";
const Switch = ({
 value,
 onClick,
}) => {
 return (
   <div>
     <div></div>
   </div>
 );
};
export default Switch;

Adding functionality to change state

Weт€™ll add an onClick function to the container div thatт€™ll change the switchт€™s state on user interaction.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import React from "react";
const Switch = ({
 value,
 onClick,
}) => {
 return (
   <div
     onClick={() => {
       onClick(!value);
     }}
   >
     <div></div>
   </div>
 );
};
export default Switch;

Additional conditional styling to reflect state

Weт€™ll now add some conditional CSS styling to reflect state. This could be done using defined CSS classes, but to stick with just JavaScript, weт€™ll use the native style prop. Hereт€™s where you can really get creative with your switchт€™s look and feel. For my design, Iт€™ll be utilizing the following techniques:

  • An absolutely positioned knob thatт€™s always 3px from the border on either state. Here, using an absolutely positioned div is clean because the switch is a fixed size.
  • Conditionally set backgroundColor

My design might have code that looks like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
import React from "react";
const SWITCH_WIDTH_PX = 72;
const HANDLE_DIAMETER_PX = 30;
const SWITCH_OFFSET_PX = 3;
const Switch = ({
 value,
 onClick,
}) => {
 return (
   <div
     style={{
       width: SWITCH_WIDTH_PX,
       height: HANDLE_DIAMETER_PX + 2 * SWITCH_OFFSET_PX,
       borderRadius: HANDLE_DIAMETER_PX,
       border: "1px #ddd solid",
       position: "relative",
       cursor: "pointer",
       background: value ? "blue" : "aliceblue",
     }}
     onClick={() => {
       onClick(!value);
     }}
   >
     <div
       style={{
         background: value ? т€œwhiteт€ : т€œblueт€,
         borderRadius: "100%",
         height: HANDLE_DIAMETER_PX,
         width: HANDLE_DIAMETER_PX,
         position: "absolute",
         top: SWITCH_OFFSET_PX,
         left: value
           ? SWITCH_WIDTH_PX - HANDLE_DIAMETER_PX - SWITCH_OFFSET_PX
           : SWITCH_OFFSET_PX,
       }}
     ></div>
   </div>
 );
};
export default Switch;

There are near-infinite ways to style your switch, so do whatever best fits your application! (And if you use any React CSS libraries like styled-components, be sure to leverage those for consistency across your application.)

Adding animation to your switch

We can use the native CSS transition property to add animation to our switch. We simply add a transition property to each element in our componentт€”both the container and the handle:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
import React from "react";
const SWITCH_WIDTH_PX = 72;
const HANDLE_DIAMETER_PX = 30;
const SWITCH_OFFSET_PX = 3;
const Switch = ({
 value,
 onClick,
}) => {
 return (
   <div
     style={{
       width: SWITCH_WIDTH_PX,
       height: HANDLE_DIAMETER_PX + 2 * SWITCH_OFFSET_PX,
       borderRadius: HANDLE_DIAMETER_PX,
       border: "1px #ddd solid",
       position: "relative",
       transition: "1s",
       cursor: "pointer",
       background: value ? "blue" : "aliceblue",
     }}
     onClick={() => {
       onClick(!value);
     }}
   >
     <div
       style={{
         background: value ? т€œwhiteт€ : т€œblueт€,
         borderRadius: "100%",
         height: HANDLE_DIAMETER_PX,
         width: HANDLE_DIAMETER_PX,
         position: "absolute",
         top: SWITCH_OFFSET_PX,
         left: value
           ? SWITCH_WIDTH_PX - HANDLE_DIAMETER_PX - SWITCH_OFFSET_PX
           : SWITCH_OFFSET_PX,
         transition: "1s",
       }}
     ></div>
   </div>
 );
};
export default Switch;

This gives the switch a natural one-second transition. Additionally, to meet a more thorough accessibility standard, you can disable transitions if a browser or OS-based т€œreduce motionт€ setting is ticked. (Separately, if youт€™re interested in learning more about animation in React, I cover that in this blog post on React animation libraries.)

Adding a hidden input box

Next, letт€™s add a hidden input box thatт€™ll act as a DOM-recognized form element that also reflects a switchт€™s state. This helps with the switchт€™s accessibility.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
import React from "react";
const SWITCH_WIDTH_PX = 72;
const HANDLE_DIAMETER_PX = 30;
const SWITCH_OFFSET_PX = 3;
const Switch = ({
 value,
 onClick,
}) => {
 return (
   <div
     style={{
       width: SWITCH_WIDTH_PX,
       height: HANDLE_DIAMETER_PX + 2 * SWITCH_OFFSET_PX,
       borderRadius: HANDLE_DIAMETER_PX,
       border: "1px #ddd solid",
       position: "relative",
       transition: "1s",
       cursor: "pointer",
       background: value ? "blue" : "aliceblue",
     }}
     onClick={() => {
       onClick(!value);
     }}
   >
     <div
       style={{
         background: value ? т€œwhiteт€ : т€œblueт€,
         borderRadius: "100%",
         height: HANDLE_DIAMETER_PX,
         width: HANDLE_DIAMETER_PX,
         position: "absolute",
         top: SWITCH_OFFSET_PX,
         left: value
           ? SWITCH_WIDTH_PX - HANDLE_DIAMETER_PX - SWITCH_OFFSET_PX
           : SWITCH_OFFSET_PX,
         transition: "1s",
       }}
     ></div>
     <input
       type="checkbox"
       value={value}
       onChange={(e) => {
         onClick(e.target.value);
       }}
       style={{ display: "none" }}
     />
   </div>
 );
};
export default Switch;

Using the native onChange function, we can easily toggle the switchт€™s value should the input box be altered with something like a screen reader.

Finally, add additional props for custom colors

If you want to alter the switchт€™s colors, we could also add some conditional declare statements to define these. Weт€™ll scope these out into intra-class variables to avoid cluttering our style inputs that can also be set as props. Altogether, the component is defined as:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
import React from "react";
const SWITCH_WIDTH_PX = 72;
const HANDLE_DIAMETER_PX = 30;
const SWITCH_OFFSET_PX = 3;
const Switch = ({
 containerCheckedColor = "blue",
 containerUncheckedColor = "aliceblue",
 handleCheckedColor = "white",
 handleUncheckedColor = "blue",
 value,
 onClick,
}) => {
 return (
   <div
     style={{
       width: SWITCH_WIDTH_PX,
       height: HANDLE_DIAMETER_PX + 2 * SWITCH_OFFSET_PX,
       borderRadius: HANDLE_DIAMETER_PX,
       border: "1px #ddd solid",
       position: "relative",
       transition: "1s",
       cursor: "pointer",
       background: value ? containerCheckedColor : containerUncheckedColor,
     }}
     onClick={() => {
       onClick(!value);
     }}
   >
     <div
       style={{
         background: value ? handleCheckedColor : handleUncheckedColor,
         borderRadius: "100%",
         height: HANDLE_DIAMETER_PX,
         width: HANDLE_DIAMETER_PX,
         position: "absolute",
         top: SWITCH_OFFSET_PX,
         left: value
           ? SWITCH_WIDTH_PX - HANDLE_DIAMETER_PX - SWITCH_OFFSET_PX
           : SWITCH_OFFSET_PX,
         transition: "1s",
       }}
     ></div>
     <input
       type="checkbox"
       value={value}
       onChange={(e) => {
         onClick(e.target.value);
       }}
       style={{ display: "none" }}
     />
   </div>
 );
};
export default Switch;

And just like that, we have a fully functional and customizable React switch component!

Closing thoughts

In this tutorial, we demonstrated how we could create a simple but personalizable React switch component to enable users to toggle boolean functions. The component built here ships with default colors, but those can be customized however you like. Additionally, the React switch is great for accessibility with its embedded native DOM element within the JSX.

Want to skip the lift? The best React component library is in Retool. Weт€™ve got a React switch component ready to goт€”give it a try.

Mathew Pregasen
Mathew Pregasen
Guest Writer
Copied
џџџџ