0

I have a list of checkboxes which when checked are added to an array via setState. I would like to convert this array into a single readable string which should change whenever the state changes and then pass this down to a child component. The checkboxes feature ages, so say for example my state is set to [7, 8, 9, 10] I want the string to be output as '7, 8, 9, 10'.

The issue I have is that when clicking a checkbox for the first time (for example one with the value of '7') readableSelectedCheckboxes is returning as 'undefined 7' despite the fact that selectedCheckboxes returns as '[7]'.

Here is my parent component which handles state.

export default class InputWithTooltip extends Component {
  constructor(props) {
    super(props);
    this.state = {
      selectedCheckboxes: [],
      readableSelectedCheckboxes: '',
    };
  }

  addCheckboxToList = (e) => {
    const clickedCheckbox = e.target.value;
    if (this.state.selectedCheckboxes.includes(clickedCheckbox)) {
      const filteredArray = this.state.selectedCheckboxes.filter(item => item !== clickedCheckbox);
      this.setState({ selectedCheckboxes: filteredArray }, () => {
        this.readableSelectedCheckboxes();
      });
    } else {
      this.setState({ selectedCheckboxes: this.state.selectedCheckboxes.concat(clickedCheckbox) }, () => {
        this.readableSelectedCheckboxes();
      });
    }
  };

  readableSelectedCheckboxes = () => {
    const selectedCheckboxes = this.state.selectedCheckboxes;
    let readableSelectedCheckboxes;

    for (let i = 0; i < selectedCheckboxes.length; i++) {
      readableSelectedCheckboxes += ` ${selectedCheckboxes[i].toString()}`;
      if (i !== selectedCheckboxes.length - 1) {
        readableSelectedCheckboxes += ',';
      }
    }
    this.setState({ readableSelectedCheckboxes });
  }

  render() {
    return (
      <CheckboxInput
        handleCheckboxChange={e => this.addCheckboxToList(e)}
        readableSelectedCheckboxes={this.state.readableSelectedCheckboxes}
        options={this.props.options}
      />
    );
  }
}

And the child component which triggers the addCheckboxToList function and should receive the string via props (minus a few variables for the sake of brevity).

export default class CheckboxInput extends Component {
  render() {
    return (
      <div>
        <h1>{this.props.readableSelectedCheckboxes}</h1>

        <div className="checkbox-container">
          {this.props.options.map((value) => {
            return (
              <div className="form-group filter-input" key={lowercaseValue}>
                <input
                  type="checkbox"
                  id={checkboxId}
                  name={inputId}
                  value={lowercaseValue}
                  onChange={this.props.handleCheckboxChange}
                />
                <label htmlFor={checkboxId} className="form-control">{value}</label>
              </div>
            );
          })}
        </div>
      </div>
    );
  }
}
GuerillaRadio
  • 1,267
  • 5
  • 29
  • 59
  • 1
    Possible duplicate of [Why calling setState method doesn't mutate the state immediately?](https://stackoverflow.com/questions/42593202/why-calling-setstate-method-doesnt-mutate-the-state-immediately) – Mayank Shukla Jul 13 '17 at 17:00
  • Possible duplicate of [this.setState doesn't update value](https://stackoverflow.com/questions/41278385/this-setstate-doesnt-update-value) – Shubham Khatri Jul 13 '17 at 17:02
  • 1
    `let readableSelectedCheckboxes = this.state.selectedCheckboxes.join(", ");` it's simpler – Thomas Jul 13 '17 at 17:11
  • @Thomas that's fixed it! Thanks very much for the elegant solution. – GuerillaRadio Jul 13 '17 at 17:15

0 Answers0