0

How to write a generic function with various state variable change based on the dropdown.

for ex:

I have dropdown 1 and dropdown 2. If I change the

dropdown 1, I need to change the few state variables like a, b, c

dropdown 2, I need to change the few state variables like x, y, z

I can do this with 2 functions. But how to write a a generic function for this?

handleChange: function(e) {
    //api call to xyz.com/getcompany/<company id> to get the job list here
    this.setState({
      selectedCompany: e.target.value,
      companychange: "company changed. New value: " + e.target.value
    })
  },

  handleChange2: function (e) {
    // api call to xyz.com/jobstatus/<job id> to get the job status\(like how many position available for this job\) here
    this.setState({
      jobchange:"job changed. New value " + e.target.value
    })
  }

Codepen: https://codepen.io/asdhanapal/pen/WmwJPj?editors=0011

Dhanapal
  • 350
  • 2
  • 7
  • 29
  • Possible duplicate of [React.js: Identifying different inputs with one onChange handler](https://stackoverflow.com/questions/21029999/react-js-identifying-different-inputs-with-one-onchange-handler) – Sudhir Dhumal Mar 02 '19 at 19:07
  • No. We can do this we i want to assign the value alone. But here, i want to change the multiple state variables based on the selection. and api call is differs based on the selection. – Dhanapal Mar 02 '19 at 19:10
  • 1
    Yes, that could theoretically be done, but the refactoring wouldn't improve the code at all, so I'd just leave it as is. – Jonas Wilms Mar 02 '19 at 19:15
  • So, writing one function won't improve the quality of the code and keeping 2 seperate function is not an issue. Am I right? – Dhanapal Mar 02 '19 at 19:21
  • Yup, exactly. ... – Jonas Wilms Mar 02 '19 at 19:24

5 Answers5

1

You could use a curried function to simplify the code a bit:

 changeToState(fn) {
    return e => this.setState(fn(e));
 }

 render() {
   //...
   <input onChange={changeToState(e => ({ selectedCompany: e.target.value, /*...*/ }))} />
   <input onChange={changeToState(e => ({ jobChange: e.target.value, /*...*/ }))} />
}

If that is still to much boilerplate, you could extract the handleChange event into a functional component:

 const StateChanger = ({ action, parent, ...props }) => (
   <input onChange={e => parent.setState(action(e))} {...props} />
 );

  // inside a component's render:
   <StateChanger parent={this} action={e => ({ selectedCompany: e.target.value })} style={{ color: red }} />

but as I already mentioned in the comments, that might remove repeated code a bit, but it doesn't improve readability / maintainability whatsoever.

Jonas Wilms
  • 132,000
  • 20
  • 149
  • 151
0

You can use below snippet:

handleChange = event => {
        const target = event.target;
        const value = target.type === 'checkbox' ? target.checked : target.value;
        const name = target.name;

        this.setState({
            [name]: value
        });
    };

Reference to react docs section: https://reactjs.org/docs/forms.html#handling-multiple-inputs

Sudhir Dhumal
  • 902
  • 11
  • 22
0

You can use following:

handleChange = event => {
  const { name, value } = event.target;
  this.setState({
    [name]:value
   })
}
// in input 
<input name="username" onChange={this.handleChange} />
Umair Farooq
  • 1,763
  • 13
  • 16
  • We can do this if value alone changed. But here, i want to change the multiple state variables based on the selection. and api call is differs based on the selection. how can I call the different api call based on the selection? – Dhanapal Mar 02 '19 at 19:12
0

Try this:

handleChange: function(source, e) {
switch(source) {
  case 'company': 
      //Need to do api call to get the job list here
      this.setState({
        selectedCompany: e.target.value,
        companychange: "company changed. New value: " + e.target.value
      })
    break;
  case 'job':
      // Need to do api call to get the job status\(like how many position available for this job\) here
      this.setState({
        jobchange:"job changed. New value " + e.target.value
      })
    break;

  };
},

 <select value={this.state.selectedCompany} onChange={this.handleChange.bind(this, 'company')}>
 <select value={this.state.selectedCompany} onChange={this.handleChange.bind(this, 'job')}>
David
  • 633
  • 8
  • 6
0

As I read your description of the requirements, there are no functional dependencies between dropdown 1 and dropdown 2, so I'd split this up in two separate components.

mzedeler
  • 4,177
  • 4
  • 28
  • 41