react: Can't update 'checked' attribute

Consider this input:

<input
    type='radio'
    value='2'
    checked={this.state.value === '1'}
    onChange={this.onChange}
/>

onChange: function (e) {
    this.setState({value: e.target.value});
}

If the first time the component is rendered, this.state.value === '1', then this input will remain checked forever in the DOM, even if it appears unchecked visually. For instance this can happen with

getInitialState = function() {
    return {value: '1'};
}

I am using React 0.14.7.

About this issue

  • Original URL
  • State: closed
  • Created 8 years ago
  • Reactions: 1
  • Comments: 29 (15 by maintainers)

Most upvoted comments

Once again, I’ll repeat that it does not make sense to talk about the native behavior here. That is, HTML does not have a concept of going from

<input type="checkbox">

to

<input type="checkbox" checked>

We created this concept. In HTML, you can do a property assignment (.value =), attribute assignment (.setAttribute), or you can blow away the entire thing and replace the whole node with .innerHTML. You can also have the user click it.

We can decide for any of these to be the behavior that React matches. None of them is the objectively correct “native behavior” so it’s misleading to talk as if that were the case.

It seems like setting the attribute is least confusing for people in most cases (so that both [checked] and :checked would work), but it’s still not clear whether that’s best, especially with forms.

@rovolution I have the same issue in react@15.4.2

from component.jsx

    render() {
        const { name, label, title } = this.props;
        const buttonClass = classnames(
            "se3-toggle-button",
            `toolbar-button-${name}`,
            "toggle-checkbox"
        );
        const checkboxId = `se3-toolbar-${name}-button`;
        const isChecked = this.state.checked;
        const currentTitle = title[isChecked];

        return (
            <div className={ buttonClass }
                title={ currentTitle }
                data-type={ ButtonTypes.TOGGLE }
                data-name={ name }>
                <input type="checkbox"
                    id={ checkboxId }
                    className="se3-toolbar-checkbox"
                    checked={ isChecked }
                    onChange={ this.handleChange }
                    data-role="item" />
                <label htmlFor={ checkboxId }
                    className="se3-toolbar-label">
                    <span className="se3-toolbar-icon"></span>
                    <span className="se3-toolbar-label-text">{ label }</span>
                </label>
            </div>
        );
    }

to html

<input type="checkbox" id="se3-toolbar-bold-button" class="se3-toolbar-checkbox" data-role="item" value="on">

When I click checkbox, It has been changed checked property internally. But the checked attribute of checkbox element’s was not displayed in chrome inspector.

image

image

I’m seeing the same problem in all browsers. Unfortunately, it’s difficult to extract a smaller example reproducing the issue. image

My workaround is to assign a different key based on the value, but I really hate it.

Why are you “meant to” update it with the property? .setAttribute() is an equal here.