简体   繁体   中英

React: inline conditionally pass prop to component

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() .

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}
    />;
  }
});

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

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

should work.

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

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.

你也可以试试这个速记方式

 <Child {...(this.props.editable  && { editable: this.props.editableOpts })} />
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}
      />
    );
  }
});

Conditionally we can pass props like this

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})} 
      />
    );
  }
});

This passes the props if they are defined. Else the props are not passed. In the other answer's the props are still passed but the value is undefined which still means the props are being passed.

Hey I might be late to jump in but I want to share a small tip. In case you are here for the reason that you want to pass props dynamically. Then you can use * sign to import all the stuff as an alias , ie in this case as grs then the imports will be in an object, then you can use that object to pass props dynamically. Hope this will help some of you.

 import * as grs from "../components/Theme"; import React from "react"; const GridInput = ({ sp, ...props }) => { return ( <Grid {...grs[`gr${sp}`]}> <Input {...props} /> </Grid> ); }; export default GridInput;
 <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

This may help you. I use this method often

    <Component
      otherProps
      {...(yourCondition ? { 
        deleteIcon: <DeleteIcon id={`${id}_icon`} />,
       }
      : {})}
    />

My take is to build an object with the wanted prop OR an empty object, and then spread it onto the child. Just 1 line of extra code before the jsx.


const EnhancedField = (props) => {

  // create an object with only the onChange prop defined if exists, or empty if not:
  const onChangeIfDefined = props.onChange ? { onChange: props.onChange } : {};
  
  return <Field
           {...onChangeIfDefined}
           name="..."
         />;

This way, if the prop is undefined or falsey, an empty object will be spread onto the child = onChange will not be passed. Both will work:

<EnhancedField name="vanilla" />
<EnhancedField name="enhanced" onChange={changeHandler} />

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM