如何有条件地向 React 组件添加属性?

IT技术 javascript reactjs
2021-01-16 11:47:13

有没有办法只在满足特定条件时向 React 组件添加属性?

我应该在渲染后基于 Ajax 调用向表单元素添加 required 和 readOnly 属性,但我不知道如何解决这个问题,因为readOnly="false"这与完全省略该属性不同。

下面的例子应该解释了我想要什么,但它不起作用。

(解析错误:意外的标识符)

function MyInput({isRequired}) {
  return <input classname="foo" {isRequired ? "required" : ""} />
}
6个回答

显然,对于某些属性,如果传递给它的值不真实,React 足够智能以省略该属性。例如:

const InputComponent = function() {
    const required = true;
    const disabled = false;

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

将导致:

<input type="text" required>

更新:如果有人对如何/为什么发生这种情况感到好奇,您可以在 ReactDOM 的源代码中找到详细信息,特别是在DOMProperty.js文件的30167

谢谢!确保该值不仅仅是一个空字符串或零,这些可能不会被删除。例如,您可以传递这样的值,如果它的值为 false,则应确保将其删除:alt={props.alt || null}
2021-03-14 11:47:13
谢谢,@杰克。我曾尝试将该属性设置为false,但仅null确保该属性已被实际删除。
2021-03-19 11:47:13
我正进入(状态 Warning: Received `false` for a non-boolean attribute `active`...
2021-03-20 11:47:13
通常的null意思是“表现得好像我根本没有指定它一样”。对于布尔 dom 属性,true/false 优于重复属性名称/false,例如<input disabled>编译为React.createElement('input', {disabled: true})
2021-03-31 11:47:13
readonly永远不会被添加,因为 React 期待该属性readOnly(大写 O)。
2021-03-31 11:47:13

juandemarco 的回答通常是正确的,但这里有另一种选择。

以你喜欢的方式构建一个对象:

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

if (condition)
  inputProps.disabled = true;

渲染传播,也可以选择传递其他props。

<input
    value="this is overridden by inputProps"
    {...inputProps}
    onChange={overridesInputProps}
 />
如果有人关心这个“糖”的精确语义,你可以看看你的 .jsx 被转译成的脚本,你会看到一个函数_extends被添加到它里面,它(在正常情况下)会props从“正常属性”并应用Object.assign(props, inputProps)
2021-03-16 11:47:13
非常简单,我使我的代码更具可读性,而没有多个条件。
2021-03-26 11:47:13
很优雅,但不应该是 inputProps.disabled = true 吗?
2021-03-31 11:47:13
这实际上非常有用,尤其是在有条件地添加许多属性时(我个人不知道可以通过这种方式完成)。
2021-04-04 11:47:13

下面是使用的示例自举Button经由阵营的自举(版本0.32.4):

var condition = true;

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

根据不同的条件,无论是{bsStyle: 'success'}{}将被退回。然后,扩展运算符会将返回对象的属性扩展到Button组件。在虚假情况下,由于返回的对象上不存在任何属性,因此不会将任何内容传递给组件。


基于Andy Polhill 评论的另一种方式

var condition = true;

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

唯一的小区别是在第二个示例中,内部组件<Button/>props对象将具有bsStyle一个值为 的undefined

@Punit,扩展运算符的优先级低于条件运算符,因此首先评估条件({bsStyle: 'success'}{}由它产生),然后扩展该对象。
2021-03-24 11:47:13
第一种方法很适合我,谢谢
2021-04-01 11:47:13
@AndyPolhill 对我来说看起来不错,并且更容易阅读代码,唯一的小区别是在您的代码示例中,内部组件<Button/>props对象将有一个bsStyle值为 的undefined
2021-04-05 11:47:13
非常简单易行的方法 <3
2021-04-05 11:47:13
以下是否会做同样的事情, <Button bsStyle={ condition ? 'success': undefined } /> 我发现语法稍微简单一些,传递undefined将省略该属性。
2021-04-07 11:47:13

这是一个替代方案。

var condition = true;

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

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

或者它的内联版本

var condition = true;

var component = (
  <div
    value="foo"
    { ...( condition && { disabled: true } ) } />
);
如果condition为假,这将尝试扩展/迭代假,我认为这是不正确的。
2021-03-26 11:47:13
+1 如果您想有条件地输出data-*aria-*属性,则需要这种方法,因为它们是 JSX 中的特例,因此data-my-conditional-attr={ false }将输出data-my-conditional-attr="false"而不是省略属性。facebook.github.io/react/docs/dom-elements.html
2021-03-27 11:47:13
我喜欢这种方法,它让我在同事中很酷。开个玩笑,从表面上看,props毕竟只是作为键值对传递的,对吗?
2021-03-28 11:47:13
@LarsNyström,这是有道理的。展开运算符只接受可迭代对象,其中false不是一个。只需与 Babel 确认即可。condition由于 Babel 实现运算符的方式,这在评估为 false时适用尽管可能是一个微不足道的解决方法...( condition ? { disabled: true } : {} ),但它会变得有点冗长。感谢您提供这么好的输入!
2021-03-31 11:47:13

这是我的一种方法。

有条件的

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

我仍然更喜欢使用常规的传递 props 的方式,因为在没有任何条件的情况下它更具可读性(在我看来)。

没有条件

<Label text={label} type={type} tooltip={tooltip} isRequired={required} />
你能解释一下这部分是如何工作的...(tooltip && { tooltip }),吗?它确实适用于组件,但是当我尝试在代码中使用类似的东西时,我收到一个错误,这意味着我尝试传播不可迭代的值
2021-04-02 11:47:13
可能是因为falseyValue && {}会返回 false,所以很可能你在传播 false 例如...(false)更好地使用完整的表达所以传播继续表现 ...(condition ? {foo: 'bar'} : {})
2021-04-12 11:47:13