Warm tip: This article is reproduced from stackoverflow.com, please click
dom forms javascript reactjs validation

Determine when at least one checkbox is checked in ReactJS

发布于 2020-03-29 21:02:41

I'm trying to determine when at least one checkbox is checked in React.

I have a Checkbox component:

import * as React from 'react';
import * as DOM from 'react-dom';
import PropTypes from 'prop-types';

class Checkbox extends React.Component {
  constructor(props) {
        super(props);
  }

    render() {
      return(
        <div>
        <label>
        <input 
      type="checkbox" 
      name={this.props.value} 
      value={this.props.value} 
      onClick={this.props.function}
      />
    <span>
      <span>
        {this.props.title}
      </span>
    </span>
  </label>
  </div>
      );
    }
}

Checkbox.PropTypes = {
  title: PropTypes.string,
  value: PropTypes.string,
  function: PropTypes.func,
}

export default NewsletterCheckbox;

It is imported and used in a parent component:

  checkFields() {
    // check if other fields are not empty and valid
    console.log(this.state);
  }
  isCheckboxChecked(event) {
    // determine if at least one checkbox is checked, and if so
    // update state
    const checkboxes = document.querySelectorAll('input[type="checkbox"]');
    const checkedOne = Array.prototype.slice.call(checkboxes).some(x => x.checked);
    if (checkedOne) {
      this.setState({ checkboxValid: true }, this.checkFields);
    } else {
      this.setState({ checkboxValid: false }, this.checkFields);
    }
  }     
  const newsletterArray = NewsletterData.map((obj) => (
    <div key={obj.value}>
      <div>
      <Checkbox
        value={obj.value}
        title={obj.title}
        function={this.isCheckboxChecked}
        />
      </div>
      <p>
          {obj.body}
          <br />
        <a onClick={(e) =>  {this.handleModal(e) }} data-iframe={obj.link}>
            See Preview
          </a>
        </p>
    </div>
  ));

The issue I'm running in to is that the function that runs when any of the checkboxes are checked, isCheckboxChecked(), once one field has been checked, if I uncheck that field (or check a bunch, and then uncheck them all), it never comes back as false.

Is there a better way of checking if at least one checkbox is checked in React without querying the DOM (which doesn't seem to work correctly with React rendered checkboxes)?

Questioner
TWLATL
Viewed
46
TBouder 2020-01-31 19:57

You should keep a counter of the checked checkbox

  <input 
    type="checkbox" 
    name={this.props.value} 
    value={this.props.value} 
    onChange={this.props.onChange} />
constructor(props) {
  super(props);
  this.state = {checkCount: 0}
}

<Checkbox
   value={obj.value}
   title={obj.title}
   onChange={(e) => {
     if (e.target.checked)
       this.setState((prevState) => ({checkCount: prevState.checkCount + 1, checkboxValid: true}))
     else {
       this.setState((prevState) => ({checkCount: prevState.checkCount - 1}), () => {
         if (this.state.checkCount === 0)
           this.setState({checkboxValid: false})
       })
     }
   }} />

We are setting the checkCount to +1 or -1 if the user checks or unchecks the checkbox. If he unchecks it, after updating the checkCount, we need to verify this.state.checkCount === 0 in order to set the checkboxValid state to false if the condition is valid.