Munsterberg
Munsterberg

Reputation: 828

React controlled radio buttons not being checked

I have a child component that receives props from a parent. In the child component it renders a couple radio buttons like this:

               <div>
                    <div className="radio">
                        <label>
                            <input
                                type="radio"
                                name="value"
                                onChange={this._handleInputChange}
                                value="1"
                                checked={this.props.value === "1"}
                            />
                            True
                        </label>
                    </div>
                    <div className="radio">
                        <label>
                            <input
                                type="radio"
                                name="value"
                                onChange={this._handleInputChange}
                                value="0"
                                checked={this.props.value === "0"}
                            />
                            False
                        </label>
                    </div>
                </div>

handleInputChange just calls a parent method like so:

_handleInputChange(e) {
    this.props.handleChange(e);
}

that will set the state of the parent component to the value selected in the radio buttons (i.e. "1" or "0"). The issue im having is that the checked conditionals return the correct props, but they function strangely. It almost seems like when the radio input receives a new prop value, it doesn't re render with checked. When the component first renders, the props.value is an empty string. When a user selects a radio button it changes the state of the parent component with _handleInputChange and then sends that value back down for the conditionals.

Upvotes: 4

Views: 23870

Answers (3)

Alex Nguyen
Alex Nguyen

Reputation: 1080

You must use state for checked property if you want react re-render radio button.

Example:

<div>
    <div className="radio">
        <label>
            <input
                type="radio"
                name="value"
                onChange={this._handleInputChange}
                value="1"
                checked={this.state.radioButton1}
            />
            True
        </label>
    </div>
    <div className="radio">
        <label>
            <input
                type="radio"
                name="value"
                onChange={this._handleInputChange}
                value="0"
                checked={this.state.radioButton2}
            />
            False
        </label>
    </div>
</div>

You also set value for state like this (alternatively, you can initialize it with getInitialState):

  this.setState({
      radioButton1 : props.value ==="1",
      radioButton2 :props.value ==="0"
  });

And in _handleInputChange function you're able to know that radio button is checked or unchecked by checking it's state.

_handleInputChange(e) {
    var isChecked = e.target.value ==="1" ? this.state.radioButton1 : this.state.radioButton2;
    this.props.handleChange(e);
}

Upvotes: 2

Munsterberg
Munsterberg

Reputation: 828

Thanks to some of the help here and on IRC I figured out it was a preventDefault in my event handler. After removing that it worked perfectly!

Upvotes: 15

holi-java
holi-java

Reputation: 30676

use bind method to bind context this._handleInputChange.bind(this) in the constructor,or use (e)=>this._handleInputChange(e) on click ,when the event handler executed normally has no context.

or declared as this below,it can bind this automatically:

class ButtonGroup extends Component{
   ....
  _handleInputChange= (e)=>{
       ...
   }

sample below:

  class ButtonGroup extends Component {
            render() {
                return (
                    <div>
                        <div className="radio">
                            <label>
                                <input
                                    type="radio"
                                    name="value"
                                    onChange={(e) => this._handleInputChange(e)}
                                    value="1"
                                    checked={this.props.value === "1"}
                                />
                                True
                            </label>
                        </div>
                        <div className="radio">
                            <label>
                                <input
                                    type="radio"
                                    name="value"
                                    onChange={(e) => this._handleInputChange(e)}
                                    value="0"
                                    checked={this.props.value === "0"}
                                />
                                False
                            </label>
                        </div>
                    </div>
                );
            }

            _handleInputChange(e) {
                this.props.handleChange(e);
            }
        }
        class Form extends Component {
            constructor(props) {
                super(props);
                this.state = {value: '1'};
            }

            render() {
                var value = this.state.value;
                return <ButtonGroup value={value} handleChange={(e) => this.valueChanged(e)}/>
            }

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

        ReactDOM.render(
            <Form />,
            document.getElementById('container')
        );

Upvotes: 0

Related Questions