2

In the following code I have two checkboxes. On-click, they change the state of the component to their respective values.

I am building a form that will need over 100 checkboxes and I don't want to write the "onChange" function for each checkbox.

Is there a way that I can write one OnChange function that will take a parameter, then set the state to that parameter?

I've tried many ways but this is still blocking me.

Thank you!

import React from 'react';

export default class InputSearch extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      inputInternship: '',
      inputMidLevel: '',
    };
    this.handleSubmit = this.handleSubmit.bind(this);
    this.onChangeInternship = this.onChangeInternship.bind(this);
    this.onChangeMidLevel = this.onChangeMidLevel.bind(this);
  }

  handleSubmit(e) {
    e.preventDefault();
    this.props.getJobData(this.state);
  }

  onChangeInternship(e) {
    this.setState({
      inputInternship: !this.state.inputInternship,
    });
    this.state.inputInternship == false? this.setState({ inputInternship: e.target.value }) : this.setState({ inputInternship: '' })
  }

  onChangeMidLevel(e) {
    this.setState({
      inputMidLevel: !this.state.inputMidLevel,
    });
    this.state.inputMidLevel == false? this.setState({ inputMidLevel: e.target.value }) : this.setState({ inputMidLevel: '' })
  }

  render() {
    return (
      <div className="search-form">
        <form onSubmit={this.handleSubmit}>

        <input type="checkbox" value="level=Internship&" checked={this.state.inputInternship} onChange={this.onChangeInternship} /> Internship <br />
        <input type="checkbox" value="level=Mid+Level&" checked={this.state.inputMidLevel} onChange={this.onChangeMidLevel} /> Mid Level <br />

          <div>
            <button
              type="submit"
            >Search
            </button>
          </div>
        </form>
      </div>
    );
  }
}
Philip Bell
  • 75
  • 1
  • 6

1 Answers1

1

You need to create a function that would return specific onChange function:

import React from 'react';

export default class InputSearch extends React.Component {
  constructor(props) {
    ...
    this.onChange = this.onChange.bind(this);
  }

  ...

  onChange(fieldName) {
    return (event) => {
      this.setState({
        [fieldName]: !this.state[fieldName],
      });

      if (this.state[fieldName]) {
        this.setState({ [fieldName]: '' })
      } else {
        this.setState({ [fieldName]: e.target.value })
      }
    }
  }

  ...

  render() {
    return (
      <div className="search-form">
        <form onSubmit={this.handleSubmit}>

        <input type="checkbox" value="level=Internship&" checked={this.state.inputInternship} onChange={this.onChange('inputInternship')} /> Internship <br />
        <input type="checkbox" value="level=Mid+Level&" checked={this.state.inputMidLevel} onChange={this.onChange('inputMidLevel')} /> Mid Level <br />

          <div>
            <button
              type="submit"
            >Search
            </button>
          </div>
        </form>
      </div>
    );
  }
}

By the way, are what is the point of changing state twice in your onChangeXYZ functions?

{
  this.setState({
    [fieldName]: !this.state[fieldName],
  });
  if (this.state[fieldName]) {
     this.setState({ [fieldName]: '' })
  } else {
     this.setState({ [fieldName]: e.target.value })
  }
}
slomek
  • 4,873
  • 3
  • 17
  • 16
  • Hey Slomek, I think I see what you're going for here and have tried to implement it. I've hacked at it to see if I can get it to work but i'm getting a 'cannot read 'setState' of undefined' – Philip Bell Oct 22 '16 at 21:24
  • You're right, I should have returned an array function from `onChange` to preserve `this` context. – slomek Oct 26 '16 at 09:01