'How to make dynamic state for multiple fields in react?

class Bills extends Component {
constructor(props) {
    super(props)
    this.state = {
        productName: '',
        price: 0,
        quantity: 0,
        noOfProductsField: 0
    }
}
handleChange = name => event => {
    this.setState({
        [name]: event.target.value,
    });
};

createFields = () => {
        const { classes } = this.props;
        let children = []
        for (let i = 0; i < this.state.noOfProductsField; i++) {
            children.push(
                <div>
                    <Select
                        className={classes.textField}
                         value = { this.state[i] }
                    onChange={this.handleChange('productName')}
                        displayEmpty
                        SelectProps={{
                            MenuProps: {
                                className: classes.menu,
                            }
                        }}>
                        <MenuItem value="" disabled>
                            Select Product
                           </MenuItem>
                        {this.state.products.map((option, ind) => (
                            <MenuItem key={ind} value={option.productName}>
                                {option.productName}
                            </MenuItem>
                        ))}
                    </Select>
                    <TextField className={classes.textField} placeholder='Price' type='number' onChange={this.handleChange('price')} />
                    <TextField className={classes.textField} placeholder='Quantity' type='number' onChange={this.handleChange('quantity')} />
                </div>
            )
        }
        return children
    }
}

I Have this function which is creating 3 input fields in for loop

  • productName
  • price
  • quantity

For Example if loop is running 2 times it will create 6 fields like image below:

Click on this to see image

So now i want to manage state for all 6 fields differently How can i do that ?



Solution 1:[1]

You can add name attribute to each input component and make one handler method which get the name as an argument.

handleInputChange(event) {

  const value = event.target.value;
  const name = event.target.name;

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

You can read more about how to handle multiple inputs on React docs.

Solution 2:[2]

you can create dynamic select field using react js

**Code sample:**

const templates = [
    {'id': 1, 'value': 'JavaScript', 'name': 'JavaScript'}, 
    {'id': 2, 'value': 'React', 'name': 'React'},    
    {'id': 3, 'value': 'Angular', 'name': 'Angular'},
    {'id': 4, 'value': 'Node', 'name': 'Node'},
    {'id': 5, 'value': 'Vue', 'name': 'Vue'},
 ]

class Dynamic extends React.Component {
  state={
    selectedTemplates: ""
  }

 onChange = (e) => {
   console.log(e)
   // selected value store into state
    this.setState({ 
      selectedTemplates: e.target.value 
    });
  };

  render() {
    return (
      <div>
        <h2>Dynamic Select(Options):</h2>
        <select className="form-control"
            value={this.state.value}
            onChange={(e) => this.onChange(e.target.value)}
          >
          {
              templates.map(msgTemplate => {
                  return (
                      <option 
                        key={msgTemplate.id} 
                        name={msgTemplate.name} 
                        value={msgTemplate.text}
                       >
                          {msgTemplate.name}
                      </option>
                  )
              })
          }
       </select>
     </div>
    )
  }
}

React.render(<Dynamic />, document.getElementById('app'));

demo >> codepen

Solution 3:[3]

Simple example for the state variables looks like:

this.state = {
test: 'hello'
}

you can get the state values dynamically by

let field_name = 'test';
let data = this.state[field_name];

you can set the state or replace the state like

let field_name = 'test';
this.setState({[field_name]: 'new'}) // test: 'new'

complex state replace like

let field_names = {key: 'test'}
this.setState({[field_name.key]: 'ok'}) // test: 'ok'
console.log(this.state[field_name.key]) // test: 'ok'

You can also use the Template literals like

this.setState({`${field_name.key}`: 'ok'}) // test: 'ok'
console.log(this.state[`${field_name.key}`]) // test: 'ok'

Superb, you got the solution.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 zb22
Solution 2 Rizwan
Solution 3