javvvva javvvva - 3 months ago 13
React JSX Question

React checkbox doesn't toggle

When I click the checkbox, the check mark doesn't disappear although the console.log in the onChange handler indicates the state changed to false. On the other hand, when the state is changed by a separate button, the check mark properly toggles on and off.

export default class TestComponent extends Component {

constructor(props) {
super(props);
this.state = {
is_checked: true
};
this.updateCheckbox = this.updateCheckbox.bind(this);
this.pressButton = this.pressButton.bind(this);
}
updateCheckbox(event) {
event.preventDefault();

this.setState({is_checked: !this.state.is_checked});
console.log(this.state.is_checked); // This logs 'false' meaning the click did cause the state change
console.log(event.target.checked); // However, this logs 'true' because the checkmark is still there

}
pressButton(event){
event.preventDefault();
this.setState({is_checked: !this.state.is_checked});
}
render(){

return (
<input type="checkbox" onChange={this.updateCheckbox} checked={this.state.is_checked} ></input>
<button onClick={this.pressButton}>change checkbox state using button</button>
);
}
}

Answer

I think I see what's happening.

You click the button, and it toggles is_checked, which either checks or unchecks the box. But that ends up triggering an onChange for the checkbox, which also toggles the state... You've actually coded an infinite loop. Although, since React batches/debounces setState operations, your code won't lock your page up.

Try this:

var React = require("react");

var Component = React.createClass({
    getInitialState: function() {
        return {
            isChecked: true
        };
    },

    handleCheckboxChange: function(event) {
        console.log("checkbox changed!", event);
        this.setState({isChecked: event.target.checked});
    },

    toggleIsChecked: function() {
        console.log("toggling isChecked value!");
        this.setState({isChecked: !this.state.isChecked});
    },

    handleButtonClick: function(event) {
        console.log("button was pressed!", event);
        this.toggleIsChecked();
    },

    render: function() {
        return (
            <div>
                <input type="checkbox" onChange={this.handleCheckboxChange} checked={this.state.isChecked} />
                <button onClick={this.handleButtonClick}>change checkbox state using this button</button>
            </div>
        );
    }
});

module.exports = Component;

Note that you can make this code even cleaner by using React's valueLink (read more here: https://facebook.github.io/react/docs/two-way-binding-helpers.html)

Comments