Conditionally setting html attributes in React.js

12,554

checked/defaultChecked take booleans, not strings.

<input className="__input"
     type="radio"
     name={self.props.radioset.name}
     value={radio.value}
     defaultChecked={radio.checked} />

jsbin demo

Side note: avoid defaultChecked/defaultValue and use checked/value with onChange instead.

Share:
12,554

Related videos on Youtube

Adam Bickford
Author by

Adam Bickford

Co-founder and CTO at Piggybank.

Updated on September 16, 2022

Comments

  • Adam Bickford
    Adam Bickford over 1 year

    I'm having a surprisingly hard time setting a default option for a radio button component in React.

    Here is my RadioToggle component:

    /** @jsx React.DOM */
    var RadioToggle = React.createClass({
      render: function () {
        var self = this;
        return (
          <div className="RadioToggle">
            {this.props.radioset.radios.map(function(radio, i){
              return (
                <label className="__option" key={i}>
                  <h3 className="__header">{radio.label}</h3>
    
                  {radio.checked ?
                    <input className="__input"
                         type="radio"
                         name={self.props.radioset.name}
                         value={radio.value}
                         defaultChecked />
    
                  : <input className="__input"
                         type="radio"
                         name={self.props.radioset.name}
                         value={radio.value} />
                  }
    
                  <span className="__label"></span>
                </label>
                )
              })
            }
          </div>
        );
      }
    });
    
    module.exports = RadioToggle;
    

    And here is how I'm creating the component:

    <RadioToggle radioset={
      {
        name: "permission_level",
        radios: [
        {
          label: "Parent",
          value: 1,
          checked: false
        },
        {
          label: "Child",
          value: 0,
          checked: true
        }
      ]}
    }/>
    

    The above code works, but we don't like generating almost identical code depending on the radio.checked option.

    The way the component is set up, I pass it a name and an array of radios to create, and for each object in the radios array use that data to create a radio button.

    In other cases I've been able to conditionally set attributes by putting ternary statements as the value, like below, but that doesn't work here.

    The problem with defaultChecked={radio.checked ? "checked" : ""} is that even with the output becoming checked="checked" on one radio button and checked on the other, it makes both radio buttons checked by default, resulting in the last one actually being checked.

    Again, the component above works, but I'm hoping someone with some more experience with React will have a cleaner way of doing it rather than generating almost identical elements except for that attribute.

    • Ross Allen
      Ross Allen over 9 years
      You can pass a context to map as the second argument rather than use var self = this. this.props.radioset.radios.map(..., this);.
  • Adam Bickford
    Adam Bickford over 9 years
    Your bin threw an error for me but I did have the checked prop a boolean (edit: nvm I see the example you were referencing). checked by itself in html without any value, or even checked=false, still marks the element as the default, so I was operating under the assumption that it was the same in React. I could've sworn that I tried your suggestion but you are right, defaultChecked=false in React doesn't output the lone checked attribute or checked=false so this will work just fine. Would you mind elaborating on your side note though? How you would use onChange to mark a default?
  • Brigand
    Brigand over 9 years
    You keep the data about which is checked in state, and update that when the user changes it, which causes the UI to update, and everything works as expected. However you can additionally render other things depending on that state, e.g. an extra form field when a certain value is selected, or you can send the data elsewhere e.g. in an ajax post request to the server when a button is clicked.
  • Alexander Suraphel
    Alexander Suraphel about 9 years
    Why avoid defaultChecked/defaultValue?
  • Brigand
    Brigand about 9 years
    It's less clear, and you often end up either directly modifying the dom, or rewriting it to use value/onChange. It also lets there be no difference between <input> and <MyCustomInput> components, api wise. It's better to do it right from the start, and consistently.
  • Jacob
    Jacob almost 9 years
    this page describes the React approach: facebook.github.io/react/docs/forms.html
  • Taysky
    Taysky almost 9 years
    @FakeRailBrigand When I open up the jsbin demo and click on the buttons they don't change values from true to false, it remains on the initial state no matter what I click. If I change "checked" to "defaultChecked" the radio buttons will respond to my clicks.
  • Con Antonakos
    Con Antonakos about 8 years
    I had an issue with defaultChecked and onClick for type='checkbox'. Using checked prop worked.