Dan Williams
Dan Williams

Reputation: 11

React - controlled component issue

So I'm working on a controlled component for a unit converter - the problem is the output is a step behind what I want it to be (e.g if I type "100" it will give the value of 10kg in lbs, "1000" -> 100 etc.). I'm sure the fix is obvious but I can't see it myself - I'm still a React newbie!

import React, { Component } from 'react';

class SearchBar extends Component {
    constructor(){
        super();
        this.state = {
            kg: '',
            lbs: '',
            value: 'kgtolbs',
            userInput: ''
        }
        this.convertKgToLbs.bind(this);
        this.convertLbsToKg.bind(this);
        this.handleOption.bind(this);
        this.handleChange.bind(this);
    }

handleOption(event){

    const selectedValue = event.target.value;
    this.setState({
        value: selectedValue
    });
}

handleChange(event){
    this.setState({
        userInput: event.target.value
    })

    if(this.state.value === 'kgtolbs'){
        this.convertKgToLbs();
    } else {
        this.convertLbsToKg();
    }
}

convertKgToLbs () {
    const kg = this.state.userInput;
    const lbsConversion = kg * 2.205;
    this.setState({
      lbs: lbsConversion.toFixed(1)
    });

}

render(
){
    return(

        <div className="search-bar">
            <input className="input" type="number" onChange={this.handleChange.bind(this)} />
            <select onChange={this.handleOption.bind(this)}>
                <option value="kgtolbs">Kg to Lbs</option>
                <option value="lbstokg">Lbs to kg</option>
            </select>
            <p>{this.state.lbs} </p>
            <p>{this.state.kg} </p>
        </div>

    );
}
}

export default SearchBar;

Any help appreciated - thanks !

Upvotes: 0

Views: 43

Answers (1)

Kevin Bai
Kevin Bai

Reputation: 631

setState is an asynchronous function. This means that in your handleChange function when you use this.state.value, the state has not actually been updated yet. setState has a callback handler to ensure do stuff after it has ran. In your case, you can do this:

handleChange(event){
    this.setState({
        userInput: event.target.value
    }, function() {
        if(this.state.value === 'kgtolbs'){
            this.convertKgToLbs();
        } else {
            this.convertLbsToKg();
        }
    });
}

Upvotes: 1

Related Questions