反应:内联有条件地将prop传递给组件


81

我想知道是否有比使用if语句更好的有条件地传递道具的方法。

例如,现在我有:

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

没有if语句,有没有办法写这个?我正在按照JSX中的一种inif-if语句的方式思考:

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

总结:我正在尝试找到一种方法来为其定义道具Child,但要传递一个值(或执行其他操作),使得Child该道具的值仍从其Child自身值中提取getDefaultProps()


您是否也可以包含代码Child?另外,您是要说<Child editableOpts={this.props.editableOpts} />而不是说<Child editable={this.props.editableOpts} />吗?
Jim Skerritt,2015年

@JimSkerritt我没有混淆道具,尽管我知道它看起来像那样。我正在尝试使用react-bootstrap-table,这就是他们使用的格式。我不确定Child代码对我要问的内容是否真正重要,这就是为什么我没有包含它的原因。我真的只是在寻找一种方法来选择性地传递或不传递道具Child,不需要在的if语句中包含大量类似的代码Parent
马修·赫伯斯特

1
疑难杂症,只是检查:)我很快就会对你有一个答案
吉姆·斯凯里特

Answers:


141

您的想法很贴切。事实证明,传递undefined道具与完全不包含道具相同,这仍会触发默认道具值。因此,您可以执行以下操作:

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

太棒了!您在某处的文档中找到了吗?我一直在寻找它,但在快速搜索中找不到任何东西
Matthew Herbst

不知道它是否在文档中,这只是我在使用React时学到的东西:)
Jim Skerritt

8
null没有配备undefinedBTW之类的力量。

2
有用的把戏!希望有很多关于如何有效使用条件渲染技术的资源
nicodjimenez

1
在这种false情况下,它不适用于我想要的方式-我仍然可以获得一个键值对property::null。单个JSX元素是否仍可能以某种方式做到这一点?
GalGrünfeld,

25

将价差运算符添加到this.props.editable

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

应该管用。


1
这不会产生与editable = {this.props.editable吗?this.props.editableOpts:undefined}还是有区别?
garyee

1
@garyee:区别在于某些组件可能会错误地 undefined视为替代(例如null,始终是替代),因此保留默认值而不是将其设置为虚假值的唯一方法是显式不传递,不传递undefined
YannDìnendal19年

@YannDìnendal如果我使用空对象而不是未定义的对象,例如<Child {...(this.props.editable?{editable:{this.props.editableOpts}}:{)},该怎么办?哪一个更好?
sktguha

1
@sktguha:是的,的确是错字,我认为:我们无法传播未定义的内容,所以,应该{}在结尾处。我会建议一个版本,谢谢:)
YannDìnendal

16

定义props变量:

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

然后在JSX中使用它:

<Child {...props} />

这是您的代码中的解决方案:

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

来源,React文档:https : //facebook.github.io/react/docs/jsx-in-depth.html#spread-attributes


我喜欢这个解决方案。我会childProps尽量避免混淆
Daniel Reina

4

实际上,如果您的prop是布尔值,则不需要实现条件,但是如果您想通过内联条件添加prop,则应如下所示:

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

希望它不会使您感到困惑。的{...手段是传播经营者喜欢通过存在的道具:{...props}editable &&手段,如果editabletrue{ editable: editableOpts }对象将与{...我们将一个新的对象喜欢它:{...{ editable: editableOpts }}它意味着editable={editableOpts},但如果this.porps.editable是真实的。


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

如果定义了道具,则通过这些道具。否则道具没有通过。在另一个答案中,道具仍然通过,但是值undefined仍然表示道具正在通过。


1
传递undefined给道具等同于根本不传递它。
马修·赫伯斯特

是的我明白。我只是想清楚一点!谢谢!
sanair96 '19

0

你也可以尝试这种简单的方法

 <Child {...(this.props.editable  && { editable: this.props.editableOpts })} />
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.