Ian Smith
Ian Smith

Reputation: 1207

Reactjs passing different properties to the same function with similar buttons?

[Noob to react]: I'm trying to do something that I think is simple, I have two number counters that have buttons to add one number to them. I want the buttons to use the same math function but pass in the property assigned to them. What ends up happening is that it seems like it's adding a string value to the prop value instead of doing a math operation and I don't fully understand why.

The simple math function:

  addOne = (event) => {
    var { target: { name, value } } = event

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

    console.log("name: " + name + "\nvalue: " + value)

  }

One of the buttons:

<button type="button" name="count2" value={this.state.count2} onClick={this.addOne} >Add One</button>

Example output:

name: count2
value: 0
name: count2
value: 01
name: count2
value: 011
name: count2
value: 0111

JS fiddle: https://jsfiddle.net/Vallamost/pf7kys5e/2/

React code:

class ButtonReuse extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
      count1: 0,
      count2: 0,
    }
  }

  addOne = (event) => {
    var { target: { name, value } } = event

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

    console.log("name: " + name + "\nvalue: " + value)

  }

  render() {
    return (
      <form onSubmit={this.handleSubmit}>
        <label>
          Counter 1: &nbsp;   <div>{this.state.count1}</div>
        <button type="button" name="count1" value={this.state.count1} onClick={this.addOne} >Add One</button>
        </label>
        <br/>
        <label>
          Counter 2: &nbsp;   <div>{this.state.count2}</div>
        <button type="button" name="count2" value={this.state.count2} onClick={this.addOne} >Add One</button>
        </label>
      </form>
    );
  }
}

ReactDOM.render(<ButtonReuse />, document.querySelector("#app"))

Upvotes: 0

Views: 136

Answers (4)

SpeedOfRound
SpeedOfRound

Reputation: 1278

Looks like a buttons value is always a string. You should not be giving the button a value like this anyways, this is very roundabout. Why not just access the state directly:

 addOne = (event) => {
    var { target: { name } } = event

    this.setState({
        [name] : this.state[name] + 1
    });

    console.log("name: " + name + "\nvalue: " + this.state[name])

  }

Then you can just remove the value from the buttons. No string conversion necessary.

Upvotes: 1

Cat_Enthusiast
Cat_Enthusiast

Reputation: 15688

It's because of JavaScript's type coersion. The value that you have in your buttons is in fact a string. So when you try to execute value + 1, JavaScript tries to resolve this by first identifying a common data-type (string) before running the calculation. To work around this, simply don't use the value stored in the button and just use the state itself.

class ButtonReuse extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
      count1: 0,
      count2: 0,
    }
  }

  addOne = (event) => {
    var { target: { name, value } } = event

    this.setState({
        [name] : this.state[name] + 1
    });

    console.log("name: " + name + "\nvalue: " + value)

  }

  render() {
    return (
      <form onSubmit={this.handleSubmit}>
        <label>
          Counter 1: &nbsp;   <div>{this.state.count1}</div>
        <button type="button" name="count1" value={this.state.count1} onClick={this.addOne} >Add One</button>
        </label>
        <br/>
        <label>
          Counter 2: &nbsp;   <div>{this.state.count2}</div>
        <button type="button" name="count2" value={this.state.count2} onClick={this.addOne} >Add One</button>
        </label>
      </form>

Upvotes: 3

vipulp
vipulp

Reputation: 196

wrap the value with parseInt() as it is being received as string from event.

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

if you'd console.log(typeof value), you'd see that it's type is string.

Upvotes: 0

ageoff
ageoff

Reputation: 2828

Your addOne method is not counting correct. Try this:

addOne = (event) => {
    var { target: { name, value } } = event

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

    console.log("name: " + name + "\nvalue: " + value)
}

Upvotes: 0

Related Questions