ReactJS: How to use boolean values in radio buttons?
Asked Answered
L

5

18

What is the proper way to use boolean data in radio buttons. The values will be converted from booleans to strings if used directly.

JSON-data for input fields that is preloaded:

var question = [
  {value: true, name: "Yes"},
  {value: false, name: "Not this time"}
]

The radio button fields:

<input type="radio" 
       name="question" 
       onChange={this.state.onRadioChange} 
       value={this.state.question[0].value} /> {this.state.question[0].name}
<input type="radio" 
       name="question" 
       onChange={this.state.onRadioChange} 
       value={this.state.question[1].value} /> {this.state.question[1].name}

The binding for onRadioChange:

onRadioChange: function(e) {
    console.log(e.target.value);
}

The console log displays that the selected values are converted from booleans to strings.

One way to handle this would be add an extra function to the onRadioChange function to convert "true"/"false" strings to booleans from e.target.value but its feels a bit hackery. Also, using just 'e.target.checked' won't work, because in some radio button groups I have other values than booleans (that needs to be passed through).

Some universal and clean solution would be to use constant values table that is transformed from and to REST.

Are there any special ReactJS way to do it? Maybe not.

Laundromat answered 31/12, 2015 at 14:25 Comment(5)
The value of an Attribute is always a String. If this value must be truthy or falsy then the only falsy String is "", i.e. !""; // trueRedingote
@PaulS. Yes, good point. With JSON-data this is quite common situation that you need to bind boolean values to radio buttons and some frameworks/libraries have automatic conversions on bindings. I want to know how people does this with react and are there some magic helpers.Laundromat
I think you can foo || '', but you may need to check your submission data after as the false selection may disappearRedingote
Does this value mean the radio button is checked? Why do you want to set the radio button value to a boolean?Kinematograph
@Kinematograph I want to keep the data structure similar to the original preloaded JSONLaundromat
L
19

Currently the solution is to convert the passed attributes from string values to boolean before saving.

var str2bool = (value) => {
   if (value && typeof value === "string") {
        if (value.toLowerCase() === "true") return true;
        if (value.toLowerCase() === "false") return false;
   }
   return value;
}

And calling the conversion:

onRadioChange: function(e) {
    console.log(str2bool(e.target.value));
    // Here we can send the data to further processing (Action/Store/Rest)
}

This way the data is ready to be send through actions to Rest or Stores and it works directly with the radio buttons.

Laundromat answered 31/12, 2015 at 15:10 Comment(0)
S
11

Use the checked attribute of input for radio buttons. That attribute uses booleans.

Selfexistent answered 31/12, 2015 at 17:1 Comment(4)
e.target.value is still string which is different type than in the original JSON (they might use same data structure in Store)Laundromat
event.target.checkedSelfexistent
Checked is probably the right way to when dealing with booleans. Although, (in this case) sometimes I need to have string values with several buttons.Laundromat
This does not work: target.checked will always be trueCatt
K
2

In case that you are looking for a way to manage the radio button checked state with React, here you have an example:

var RadioButtons = React.createClass({
  getInitialState: function () {
    // Assuming there is always one option set to true.
    return {
      question: this.props.options.filter(function (option) {
        return option.value;
      })[0].name
    };
  },
  onRadioChange: function (e) {
    this.setState({
      question: e.target.value
    });
  },
  render: function () {
    var options = this.props.options.map(function (option, key) {
      return (
        <li key={key}>
          <input type="radio" 
             name="question" 
             onChange={this.onRadioChange} 
             checked={this.state.question === option.name}
             value={option.name} /> {option.name}
        </li>
      );
    }, this);
    return (
      <ul style={{listStyle: 'none'}}>
        {options}
      </ul>
    );
  }
});

This component can then be used passing your question list as properties:

<RadioButtons options={question} />

Check this fiddle.

Kinematograph answered 31/12, 2015 at 17:10 Comment(0)
C
2

The best solution to handle yes/no is a checkbox because you can use a boolean with the help of target.checked. If you want to use 2 radios instead unfortunately the simplest solution is to rely on strings.

You cannot use target.checked with radios (proposed in one of the answers) because it will always be true. If you click on the first radio, its target.checked inside handleChange() will be true, then if you click on the second radio its target.checked will also be true (e.g you'll never get false).

function handleChange(e) {
  const value = e.target.value;
  setState({answer: value});
}

<input
  type="radio"
  name="answer"
  onChange={handleChange}
  value="yes"
  checked={answer === "yes"}
/> Yes

<input
  type="radio"
  name="answer"
  onChange={handleChange}
  value="no"
  checked={answer === "no"}
/> Not this time

Full example: https://codesandbox.io/s/stack-overflow-34547733-nc04l

Catt answered 4/6, 2019 at 15:37 Comment(0)
F
0

When working with binary (true or false valued) radio buttons in in React use a truthy and a falsy string for each input value and then in your handleChange function use either: Boolean(ev.target.value) or !!ev.target.value. This will convert whatever string you have in ev.target.value into boolean.

Example:

       <input
        type="radio"
        name="radioButtonField"  
        value="foo"    //a truthy string 
        onChange={(ev) =>
          setState((currentState) => ({
            ...currentState,
            [ev.target.name]: Boolean(ev.target.value),
          }))
        }
      />
      <input
        type="radio"
        name="radioButtonField"
        value=""       //a falsy string
        onChange={(ev) =>
          setState((currentState) => ({
            ...currentState,
            [ev.target.name]: Boolean(ev.target.value),
          }))
        }
      />
Fan answered 5/3, 2022 at 10:58 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.