React: inline conditionally pass prop to component
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 })} />
Comments
-
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 thatChild
still pulls that prop's value fromChild
's owngetDefaultProps()
. -
Matthew Herbst almost 9 yearsOh, awesome! Did you find that in documentation somewhere? I was looking for that but couldn't find anything during a quick search
-
Jim Skerritt almost 9 yearsnot sure if it's in the documentation or not, just something I've learned while using React :)
-
Season almost 8 years
null
is not armed with such power asundefined
, BTW. -
nicodjimenez almost 7 yearsuseful trick! wish there were good resources on how to effectively use conditional rendering techniques
-
Gal Grünfeld over 5 yearsIn 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 about 5 yearsDoes this not yield the same result as editable= {this.props.editable ? this.props.editableOpts : undefined} Or is there a difference?
-
Yann Dìnendal almost 5 years@garyee: the difference is that some components might incorrectly treat
undefined
as an override (likenull
, 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 passundefined
. -
Matthew Herbst over 4 yearsPassing
undefined
to a prop is equivalent to not passing it at all. -
Daniel Reina about 4 yearsI like this solution. I'd use
childProps
to avoid confusion though -
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 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 about 3 yearsI 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, examiningObject.keys(props)
will reveal properties that have been set - even to the value ofundefined
. This matters for certain components which function as both controlled and uncontrolled components based on which props are set. -
pishpish about 3 years@MatthewHerbst That is not true. Passing
undefined
is not the same as not passing at all. -
Matthew Herbst about 3 years@pishpish indeed it is. Try it.
-
pishpish about 3 yearsOh man, I thought this was an Angular thread. Sorry.
-
sanair96 almost 3 years@MatthewHerbst My bad. I was under the illusion that passing undefined was equivalent to passing props.
-
Martin over 2 yearsWouldn't this cause a runtime error when
this.props.editable
is false because the spread operator would try to spread a boolean? -
aryankarim about 2 yearsI have been using this technique for a while now. Does this have any drawbacks?
-
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 about 2 yearsAnd @aryankarim, thanks for upvoting me,
-
Normal about 2 yearsthe expression can be simplified as
<Child {...(this.props.editable && { editable: this.props.editableOpts })} />