Build a reusable Checkbox Group component in React with material-ui

Harshal Patil
3 min readFeb 26, 2019

--

While working with React, customizing the default checkbox as per our needs has been a challenge at one or the other point of time during the web development.

So, in such cases using material-ui (a React component library) can come handy. It has a vast collection of react component which can be used across our projects with minimal configuration. One such component which we’ll be using today is a checkbox to create a reusable checkbox group example.

Things required to start with the use case:

  • Basic environment set up to write and execute the code. You could go with either of these alternatives to start with:
  1. You could prefer to go with any online code editors such as stackblitz or codesandbox and choose to react framework over there to start with.
  2. Or, you can go with the local environment set up for a react application. You can refer the official react docs here to help you get started.

Before starting with creating our component, this is how our use case will look like after the implementation

So, lets begin with creating the component.

Step 1. Configure Checkbox component from material-ui library

  • Install @material-ui/core as a dependency in your package.json
  • The following code snippet will help you in creating the component.

We’ll wrap the checkbox component called from material-ui library with FormControlLabel component as the checkbox is a form related component. The props we are going to pass to the checkbox are: checked to check if the checkbox is checked, the onChange event handler which will return a callback to its parent component i.e. from where it was called, the value, its label, and classes to apply for styling.

Now, this component can be called in its parent checkbox group component by passing the props that it required in order to get rendered as below:

<CheckboxItem
key={index}
checkboxLabel={aCheckbox.label}
checkboxValue={aCheckbox.value}
checked={aCheckbox.checked}
checkboxChangeCallback={(checkStatus) => this.handleChildCheckboxChange(checkStatus, index)}
/>

Step 2. Passing the default checkbox group configuration from the main component

So, before implementing the main checkbox group logic, let’s be done with passing the default checkbox group configuration from App.js as below:

here, we are passing 3 keys viz. label, value, checked to correspond to a checkbox that we want to render. One thing to notice here is that we are storing the state of all the checkboxes in the main parent component by receiving the latest state through a callback and thereby maintaining a single source of truth.

Step 3. Implementing the logic for the given use case

So, now comes the core part of this use case wherein we’ll be writing the logic for selecting/ deselecting the checkboxes.

There’ll be 3 main parts to this component. So, if ‘All’ selector is checked then it should update all the checkboxes with its own check status as follows:

handleParentCheckboxChange = (isChecked) => {
const { checkboxes, onCheckboxGroupChange } = this.props;
const newCheckState = checkboxes.map((aCheckbox) => ({
...aCheckbox,
checked: isChecked
}));
onCheckboxGroupChange(newCheckState);
};

here, we’ll receive the check status of the parent in a callback from CheckboxItem component and we’ll change the statuses of all the checkboxes with the status received. The same will happen when any child is clicked among the group of checkboxes.

Lastly, we want this whole use case to be in sync i.e. there shouldn’t be any inconsistency in the status of the children checked and their parent selector. For this, we’ll call the following method whenever our component is mounted or it receives any updates as below:

// Calling updateParentWithChildren() methodcomponentWillReceiveProps(nextProps) {
this.updateParentWithChildren(nextProps);
}
componentWillMount() {
this.updateParentWithChildren(this.props);
}
// The method being calledupdateParentWithChildren = (props) => {
const { checkboxes } = props;
let allChecked = false;
for (let i = 0; i < checkboxes.length; i += 1) {
if (checkboxes[i].checked) {
allChecked = true;
} else {
allChecked = false;
break;
}
}
this.setState({
parentCheckboxChecked: allChecked
});
};

The CheckboxGroup component as a whole would look something like this:

You can access the github repo for this use case by clicking here.

So, this was one approach to implement the given use case with React and material-ui, kindly comment below to let others know if you could come up with a better approach to this.

Thanks a lot for reaching up to here. 😄

--

--