How to conditionally add attributes to React components?

How to conditionally add attributes to React components?

Is there a way to only add attributes to a React component if a certain condition is met?
I’m supposed to add required and readOnly attributes to form elements based on an ajax call after render, but I can’t see how to solve this since readOnly=”false” is not the same as omitting the attribute completely.
The example below should explain what I want, but wont work (Parse Error: Unexpected identifier).
var React = require(‘React’);

var MyOwnInput = React.createClass({
render: function () {
return (

);
}
});

module.exports = React.createClass({
getInitialState: function () {
return {
isRequired: false
}
},
componentDidMount: function () {
this.setState({
isRequired: true
});
},
render: function () {
var isRequired = this.state.isRequired;

return (

);
}
});

Solutions/Answers:

Solution 1:

Apparently, for certain attributes, React is intelligent enough to omit the attribute if the value you pass to it is not truthy. For example:

var InputComponent = React.createClass({
    render: function() {
        var required = true;
        var disabled = false;

        return (
            <input type="text" disabled={disabled} required={required} />
        );
    }
});

will result in:

<input type="text" required data-reactid=".0.0">

Solution 2:

Just throwing another option out there, but @juandemarco’s answer is usually correct.

Build an object how you like:

var inputProps = {
  value: 'foo',
  onChange: this.handleChange
};

if (condition) inputProps.disabled = true;

Render with spread, optionally passing other props also.

<input 
    value="this is overridden by inputProps" 
    {...inputProps} 
    onChange={overridesInputProps}
 />

Solution 3:

Here is an example of using Bootstrap‘s Button via React-Bootstrap.

var condition = true;

return (
  <Button {...(condition ? {bsStyle: 'success'} : {})} />
);

Depending on the condition, either {bsStyle: 'success'} or {} will be returned. The spread operator will then spread the properties of the returned object to Button component. In the falsy case, since no properties exist on the returned object, nothing will be passed to the component.


Alternative way based on @Andy Polhill’s comment below:

var condition = true;

return (
  <Button bsStyle={condition ? 'success' : undefined} />
);

The only small difference is that in the 2nd example inner component <Button/>‘s props object will have a key bsStyle with value of undefined.

Solution 4:

Late to the party. Here is an alternative.

var condition = true;

var props = {
  value: 'foo',
  ...( condition && { disabled: true } )
};

var component = <div { ...props } />;

Or its inline version

var condition = true;

var component = (
  <div
    value="foo"
    { ...( condition && { disabled: true } ) } />
);

Solution 5:

You can use the same shortcut, which is used to add/remove (parts of) components ({isVisible && <SomeComponent />}).

class MyComponent extends React.Component {
  render() {
    return (
      <div someAttribute={someCondition && someValue} />
    );
  }
}

Solution 6:

Here’s a way I do it.

with Conditional:

  <Label
    {...{
      text: label,
      type,
      ...(tooltip && { tooltip }),
      isRequired: required
    }}
  />

I still prefer using the regular way of passing props down because it is more readable (in my opinion) in the case of not have any conditionals.

with No conditional:

 <Label text={label} type={type} tooltip={tooltip} isRequired={required} />