React: inline conditionally pass prop to component

96,219

Solution 1

You were close with your idea. It turns out that passing undefined for a prop is the same as not including it at all, which will still trigger the default prop value. So you could do something like this:

var parent = React.createClass({
  propTypes: {
    editable: React.PropTypes.bool.isRequired,
    editableOpts: React.PropTypes.shape({...})
  },
  render: function() {
    return <Child 
      editable={this.props.editable ?
                  this.props.editableOpts : 
                  undefined}
    />;
  }
});

Solution 2

Add a spread operator to the this.props.editable:

<Child {...(this.props.editable ? {editable: this.props.editableOpts} : {})} >

should work.

Solution 3

Define props variable:

let props = {};
if (this.props.editable){
  props.editable = this.props.editable;
}

And then use it in JSX:

<Child {...props} />

Here is a solution in your code:

var parent = React.createClass({
  propTypes: {
    editable: React.PropTypes.bool.isRequired,
    editableOpts: React.PropTypes.shape({...})
  },
  render: function() {
    let props = {};
    if (this.props.editable){
      props.editable = this.props.editable;
    }
    return (
      <Child {...props} />
    );
  }
});

Source, React documentation: https://facebook.github.io/react/docs/jsx-in-depth.html#spread-attributes

Solution 4

Actually, if your prop is boolean it isn't needed to implement condition but if you wanna add prop by inline condition you should write like below:

const { editable, editableOpts } = this.props;
return (
  <Child {...(editable && { editable: editableOpts } )} />
);

Hope it doesn't confuse you. the {... means it is spread operator like passing existed props: {...props} and the editable && means if editable is true the { editable: editableOpts } object will make and with {... we will make a new object like it: {...{ editable: editableOpts }} that it means editable={editableOpts} but if this.porps.editable is true.

Solution 5

also you can try this short hand way

 <Child {...(this.props.editable  && { editable: this.props.editableOpts })} />
Share:
96,219
Matthew Herbst
Author by

Matthew Herbst

#SOReadyToHelp

Updated on July 20, 2022

Comments

  • Matthew Herbst
    Matthew Herbst almost 2 years

    I would like to know if there is a better way to conditionally pass a prop than using an if-statement.

    For example, right now I have:

    var parent = React.createClass({
      propTypes: {
        editable: React.PropTypes.bool.isRequired,
        editableOpts: React.PropTypes.shape({...})
      },
      render: function() {
        if(this.props.editable) {
          return (
            <Child editable={this.props.editableOpts} />
          );
        } else {
          // In this case, Child will use the editableOpts from its own getDefaultProps()
          return (
            <Child />
          );
        }
      }
    });
    

    Is there a way to write this without the if-statement? I am was thinking something along the lines of a type of inline-if-statement in the JSX:

    var parent = React.createClass({
      propTypes: {
        editable: React.PropTypes.bool.isRequired,
        editableOpts: React.PropTypes.shape({...})
      },
      render: function() {
        return (
          <Child 
            {this.props.editable ? editable={this.props.editableOpts} : null} 
          />
        );
      }
    });
    

    To wrap-up: I'm trying to find a way to define a prop for Child, but pass a value (or do something else) such that Child still pulls that prop's value from Child's own getDefaultProps().

  • Matthew Herbst
    Matthew Herbst almost 9 years
    Oh, awesome! Did you find that in documentation somewhere? I was looking for that but couldn't find anything during a quick search
  • Jim Skerritt
    Jim Skerritt almost 9 years
    not sure if it's in the documentation or not, just something I've learned while using React :)
  • Season
    Season almost 8 years
    null is not armed with such power as undefined, BTW.
  • nicodjimenez
    nicodjimenez almost 7 years
    useful trick! wish there were good resources on how to effectively use conditional rendering techniques
  • Gal Grünfeld
    Gal Grünfeld over 5 years
    In the false case it doesn't work for me the way I wanted - I still get a key-value pair: property: null. Is it still possible to do it somehow with a single JSX element?
  • Flummiboy
    Flummiboy about 5 years
    Does this not yield the same result as editable= {this.props.editable ? this.props.editableOpts : undefined} Or is there a difference?
  • Yann Dìnendal
    Yann Dìnendal almost 5 years
    @garyee: the difference is that some components might incorrectly treat undefined as an override (like null, which is always an override) so the only way to keep the default value instead of setting it to a falsy value is to explicitly not pass it, not pass undefined.
  • Matthew Herbst
    Matthew Herbst over 4 years
    Passing undefined to a prop is equivalent to not passing it at all.
  • Daniel Reina
    Daniel Reina about 4 years
    I like this solution. I'd use childProps to avoid confusion though
  • sktguha
    sktguha almost 4 years
    @YannDìnendal what if I use an empty object instead of undefined, like <Child {...(this.props.editable ? {editable: {this.props.editableOpts}} : {)} > Does it make any difference? which one is better?
  • Yann Dìnendal
    Yann Dìnendal almost 4 years
    @sktguha : yes indeed, looks like a typo I think: we can't spread undefined so yes, it should be a {} at the end. I'll suggest an edition, thanks :)
  • nicholas
    nicholas about 3 years
    I know this answer is quite old, so I do not know if things have changed in the interim, but for anyone stumbling across this answer in 2021: passing undefined as a prop is not the same as not setting the prop at all. Within a component, examining Object.keys(props) will reveal properties that have been set - even to the value of undefined. This matters for certain components which function as both controlled and uncontrolled components based on which props are set.
  • pishpish
    pishpish about 3 years
    @MatthewHerbst That is not true. Passing undefined is not the same as not passing at all.
  • Matthew Herbst
    Matthew Herbst about 3 years
    @pishpish indeed it is. Try it.
  • pishpish
    pishpish about 3 years
    Oh man, I thought this was an Angular thread. Sorry.
  • sanair96
    sanair96 almost 3 years
    @MatthewHerbst My bad. I was under the illusion that passing undefined was equivalent to passing props.
  • Martin
    Martin over 2 years
    Wouldn't this cause a runtime error when this.props.editable is false because the spread operator would try to spread a boolean?
  • aryankarim
    aryankarim about 2 years
    I have been using this technique for a while now. Does this have any drawbacks?
  • AmerllicA
    AmerllicA about 2 years
    @aryankarim, I'm still using this, not at all bad, it's awesome for when you don't want pass any key as props to the Child component.
  • AmerllicA
    AmerllicA about 2 years
    And @aryankarim, thanks for upvoting me,
  • Normal
    Normal about 2 years
    the expression can be simplified as <Child {...(this.props.editable && { editable: this.props.editableOpts })} />