stephencurry30
stephencurry30

Reputation: 127

React - how to make only one increment function setState multiple variables?

How can I simplify this code so that I don't need to a have a separate Increment function for each quantity variable?

Is there a way to pass parameters? I also have to add decrement functions for each quantity variable.

import React, { Component } from 'react';
import './App.css';

class App extends Component {
    // Define data above render()
    constructor(){
      super(); 

      this.state = {
        quantity1: 0,
        quantity2: 0,
        quantity3: 0,
        quantity4: 0,
        quantity5: 0,
        quantity6: 0,
      }      

    }

    onChange (event) {
      this.setState({ value: event.target.value })
    }

    IncrementItem = () => {
      this.setState({ quantity1: this.state.quantity1 + 1 });
    }

    IncrementItem2 = () => {
      this.setState({ quantity2: this.state.quantity2 + 1 });
    }

    IncrementItem3 = () => {
      this.setState({ quantity3: this.state.quantity3 + 1 });
    }

    render() {
        // Show data in React expression.
        return( 
            <div>
                Server name: <input type="text" value={this.state.value} onChange={event => this.onChange(event)} /><br></br>
                <br></br>

                 Server: {this.state.value}<br></br>
                 <button onClick={this.Reset}>Reset</button>

                  <table>
                    <tr>
                      <td>Item1</td>
                      <td>0.99</td>
                      <td><button onClick={this.IncrementItem}>+</button> <button onClick={this.DecreaseItem}>-</button></td>
                      <td>{this.state.quantity1}</td>
                    </tr>
                    <tr>
                    <tr>
                      <td>Item2</td>
                      <td>0.99</td>
                      <td><button onClick={this.IncrementItem2}>+</button> <button onClick={this.DecreaseItem2}>-</button></td>
                      <td>{this.state.quantity2}</td>
                    </tr>
                    <tr>
                  </table>
            </div>
        );     
    }
}

Upvotes: 1

Views: 1528

Answers (3)

Alexandre Lara
Alexandre Lara

Reputation: 2568

If you use name in your buttons, you can retrieve it from the click event.

IncrementItem = (e) => {
    const { name } = e.target;

    this.setState(prevState => ({ [name]: prevState[name] + 1 }));
}

DecreaseItem = (e) => {
    const { name } = e.target;

    this.setState(prevState => ({ [name]: prevState[name] - 1 }));
}

Set name in your buttons to be exactly the same as in your state:

<table>
  <tr>
    <td>Item1</td>
    <td>0.99</td>
    <td><button onClick={this.IncrementItem} name='quantity1'>+</button> <button onClick={this.DecreaseItem} name='quantity1'>-</button></td>
    <td>{this.state.quantity1}</td>
  </tr>
  <tr>
  <tr>
    <td>Item2</td>
    <td>0.99</td>
    <td><button onClick={this.IncrementItem} name='quantity2'>+</button> <button onClick={this.DecreaseItem} name='quantity2'>-</button></td>
    <td>{this.state.quantity2}</td>
  </tr>
  <tr>
</table>

Upvotes: 0

Titus
Titus

Reputation: 22474

You can use the same method as you've used for the onChange function, which is to determine the property name based on which element called the function.

Something like this:

increment = (propName) => {
    this.setState(prevState => ({[propName]: ++prevState[propName]}))
}

and to call it with the appropriate parameter, you can use bind:

<button onClick={this.increment.bind(this, 'quantity1')}>+</button>

Or something like this:

<button onClick={() => this.increment('quantity1')}>+</button>

Upvotes: 1

Dacre Denny
Dacre Denny

Reputation: 30360

Perhaps you could define a single and generalised increment function like so, that takes the key of the state value that you want to increment:

IncrementItemByKey = (key) => {

  const lastValue = this.state[ key ];

  this.setState({ [ key ]: lastValue + 1 });
}

DecreaseItemByKey = (key) => {

  const lastValue = this.state[ key ];

  this.setState({ [ key ]: lastValue - 1 });
}

And then use it like so, passing in the "quantity" key that you want to increment and decrement per button:

<table>
  <tr>
    <td>Item1</td>
    <td>0.99</td>
    <td>
    <button onClick={ () => this.IncrementItemByKey('quantity1') }>+</button>
    <button onClick={ () => this.DecreaseItemByKey('quantity1') }>-</button></td>
    <td>{this.state.quantity1}</td>
  </tr>
  <tr>
  <tr>
    <td>Item2</td>
    <td>0.99</td>
    <td>
    <button onClick={ () => this.IncrementItemByKey('quantity2') }>+</button> 
    <button onClick={ () => this.DecreaseItemByKey('quantity2') }>-</button></td>
    <td>{this.state.quantity2}</td>
  </tr>
  <tr>
</table>

Upvotes: 0

Related Questions