ChatGPT解决这个技术问题 Extra ChatGPT

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

如果满足特定条件,有没有办法只向 React 组件添加属性?

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

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

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

function MyInput({isRequired}) {
  return <input classname="foo" {isRequired ? "required" : ""} />
}
可能是一条评论对某人有帮助,我发现 React 16.7 doesnt rerenders 并更新组件的 html 属性,如果您仅在商店(fe redux)中更改它们并绑定到组件.这意味着组件有 fearia-modal=true,您将更改(为 false)推送到 aria/data 属性的存储区,但没有其他任何更改(例如组件的内容或类或变量) ) 结果 ReactJs 不会更新该组件中的 aria/data attrs。我一直在胡闹一整天才意识到这一点。

G
Gian Marco Toso

显然,对于某些属性,如果您传递给它的值不真实,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 行。


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

juandemarco's answer 通常是正确的,但这里有另一个选项。

以您喜欢的方式构建对象:

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

if (condition) {
  inputProps.disabled = true;
}

使用传播进行渲染,也可以选择传递其他道具。

<input
    value="this is overridden by inputProps"
    {...inputProps}
    onChange={overridesInputProps}
 />

这实际上非常有用,尤其是在有条件地添加许多属性时(我个人不知道可以这样做)。
很优雅,但不应该是 inputProps.disabled = true 吗?
非常简单,我在没有多个条件的情况下使我的代码更具可读性。
如果有人关心这个“糖”的精确语义,你可以查看你的 .jsx 被转译成的脚本,你会看到一个函数 _extends 已添加到其中,这将(在正常情况下)占用props 从“正常属性”构造并应用 Object.assign(props, inputProps)
P
Peter Mortensen

以下是通过 React-Bootstrap(版本 0.32.4)使用 BootstrapButton 的示例:

var condition = true;

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

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

基于 Andy Polhill's comment 的另一种方法:

var condition = true;

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

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


@Punit,扩展运算符的优先级低于条件运算符,因此首先评估条件({bsStyle: 'success'}{} 结果),然后扩展该对象。
以下是否会做同样的事情 <Button bsStyle={ condition ? 'success': undefined } /> 我发现语法稍微容易一些,传递 undefined 将省略该属性。
@AndyPolhill 对我来说看起来不错,并且更容易阅读代码,唯一的小区别是在您的代码示例中,内部组件 <Button/>props 对象将有一个值为 undefined 的键 bsStyle
这是唯一允许单选按钮在未设置 onChange 的情况下不对设置的 checked 值发出警告的解决方案(即使 checked 被设置为 false)。所以{...(checked ? {checked} : {})}。感谢您的解决方案!
解决了我的问题!谢谢。这是我如何使用它的示例,有条件地传播 React Native 样式类:style={{...(isReadOnly ? styles.readOnly : {}), ...styles.baseStyle }} 然后,在组件内部,您可以将它混合到组件使用的任何样式中:<Text style={...props.style, ...localStyleClass} >Hello World<Text>
j
jonschlinkert

这是一个替代方案。

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

我喜欢这种方法,它让我在同事中很酷。开个玩笑,从表面上看,props 只是作为键值对传递的,对吗?
如果 condition 为 false,这将尝试扩展/迭代 false,我认为这是不正确的。
@LarsNyström,这是有道理的。扩展运算符只接受可迭代对象,其中 false 不是一个。只需与 Babel 核对即可。当 condition 评估为 false 时,这适用于它,因为 Babel 实现运算符的方式。虽然一个简单的解决方法可能是 ...( condition ? { disabled: true } : {} ),但它变得有点冗长。感谢您的精彩输入!
+1 如果您想有条件地输出 data-*aria-* 属性,则需要此方法,因为它们是 JSX 中的特殊情况,因此 data-my-conditional-attr={ false } 将输出 data-my-conditional-attr="false" 而不是省略属性。 facebook.github.io/react/docs/dom-elements.html
永远第一次登录只是为了给这个投票。我想提供条件对象值是我 - 实际上 - 寻找的。
P
Peter Mortensen

这是我这样做的一种方式。

有条件:

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

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

无条件:

<Label text={label} type={type} tooltip={tooltip} isRequired={required} />

您能否解释一下这部分的工作原理 - ...(tooltip && { tooltip }),?它确实适用于组件,但是当我尝试在代码中使用类似这样的东西时,我收到一个错误,这意味着我尝试传播不可迭代的值
可能是因为 falseyValue && {} 将返回 false,因此您很可能在传播 false,例如 ...(false)。使用完整表达式要好得多,因此传播继续表现...(condition ? {foo: 'bar'} : {})
P
Peter Mortensen

假设如果条件为真,我们想要添加自定义属性(使用 aria-* 或 data-*):

{...this.props.isTrue && {'aria-name' : 'something here'}}

假设如果条件为真,我们要添加样式属性:

{...this.props.isTrue && {style : {color: 'red'}}}

G
GijsjanB

您可以使用相同的快捷方式,用于添加/删除(部分)组件 ({isVisible && <SomeComponent />})。

class MyComponent extends React.Component {
  render() {
    return (
      <div someAttribute={someCondition && someValue} />
    );
  }
}

如果 someCondition 为真但 someValue 为假(例如 false 本身或 0 等),是否仍包含该属性?如果需要显式包含一个虚假值,例如坐标属性的 0 等,这一点很重要。
通常,该属性会被省略,但在 data-*aria-* 的情况下不会,请参阅我上面的评论。如果您引用该值,或将其转换为字符串,则该属性将显示:例如 someAttr={ `${falsyValue}` } 可以呈现 someAttr="false"
P
Peter Mortensen

如果你使用 ECMAScript 6,你可以简单地这样写。

// First, create a wrap object.
const wrap = {
    [variableName]: true
}
// Then, use it
<SomeComponent {...{wrap}} />

在哪里可以找到有关此语法的文档?
P
Peter Mortensen

这应该可行,因为您的状态将在 Ajax 调用后发生变化,并且父组件将重新呈现。

render : function () {
    var item;
    if (this.state.isRequired) {
        item = <MyOwnInput attribute={'whatever'} />
    } else {
        item = <MyOwnInput />
    }
    return (
        <div>
            {item}
        </div>
    );
}

T
Tim

使用 undefined 适用于大多数属性:

const name = "someName";

return (
    <input name={name ? name : undefined} />
);

J
Jonas Sciangula Street

例如使用自定义容器的属性样式

const DriverSelector = props => {
  const Container = props.container;
  const otherProps = {
    ...( props.containerStyles && { style: props.containerStyles } )
  };

  return (
    <Container {...otherProps} >

g
golopot

对于 React [1] 列出的一些布尔属性:

<input disabled={disabled} />

// renders either `<input>` or `<input disabled>` 

对于其他属性:

<div aria-selected= {selected ? "" : undefined} />

// renders either `<div aria-selected></div>` or `<div></div>`

[1] 布尔属性列表:https://github.com/facebook/react/blob/3f9480f0f5ceb5a32a3751066f0b8e9eae5f1b10/packages/react-dom/src/shared/DOMProperty.js#L318-L345


这是最好的答案。为什么要进一步复杂化?
P
Peter Mortensen

在 React 中,你可以有条件地渲染组件,也可以渲染它们的属性,比如 props、className、id 等等。

在 React 中,使用 ternary operator 是一种很好的做法,它可以帮助您有条件地渲染组件。

一个示例还展示了如何有条件地渲染 Component 及其样式属性。

这是一个简单的例子:

类 App 扩展 React.Component { state = { isTrue: true }; render() { return (

{this.state.isTrue ? ( ) : ( )}
); } } ReactDOM.render(, document.getElementById("root"));


这可能会因为很多属性而变得非常混乱。我更喜欢传播变体。
是的,您是对的,但这适用于需要了解概述的人,我将再举一个例子。但要保持简单。
l
lifeisfoo

从我的角度来看,管理多个条件 props 的最佳方法是 @brigand 的 props object 方法。但可以改进它以避免为每个条件道具添加一个 if 块。

ifVal 助手

随意重命名(iv,condVal,cv,_,...)

如果满足条件,您可以定义一个辅助函数来返回一个值或另一个值:

// components-helpers.js
export const ifVal = (cond, trueValue=true, falseValue=null) => {
  return cond ? trueValue : falseValue
}

如果 condtrue(或 truthy),则返回 trueValue - 或 true。如果 condfalse(或 falsy),则返回 falseValue - 或 null

这些默认值(truenull)通常是允许将 prop 传递或不传递给 React 组件的正确值。您可以将此函数视为“改进的 React 三元运算符”。如果您需要对返回值进行更多控制,请对其进行改进。

让我们将它与许多道具一起使用。

构建(复杂的)道具对象

// your-code.js
import { ifVal } from './components-helpers.js'

// BE SURE to replace all true/false with a real condition in you code
// this is just an example

const inputProps = {
  value: 'foo',
  enabled: ifVal(true), // true
  noProp: ifVal(false), // null - ignored by React
  aProp: ifVal(true, 'my value'), // 'my value'
  bProp: ifVal(false, 'the true text', 'the false text') // 'my false value',
  onAction: ifVal(isGuest, handleGuest, handleUser) // it depends on isGuest value
};

 <MyComponent {...inputProps} />

这种方法类似于使用 classnames utility 有条件地管理类的流行方法,但适用于 props。

为什么你应该使用这种方法

即使有许多条件 props,您也将拥有清晰易读的语法:每个新 prop 只需在对象声明中添加一行代码。

通过这种方式,您可以替换重复运算符(...&&? :、...)的语法噪音,当您有许多道具时,这可能会非常烦人,函数调用。

作为开发人员,我们的首要任务是编写最明显的代码来解决问题。太多次我们为自我解决问题,在不需要的地方增加了复杂性。对于今天的我们、明天的我们和我们的伙伴,我们的代码应该简单明了。

仅仅因为我们可以做某事并不意味着我们应该

我希望这个迟到的回复会有所帮助。


井井有条!我很惊讶为什么这个答案没有投票!
a
aadilraza339
<input checked={true} type="checkbox"  />

一些解释将使这是一个更好的答案。
V
Vishav

在反应功能组件中,您可以尝试这样的事情来省略不必要的标签属性。

<div className="something" ref={someCondition ? dummyRef : null} />

如果我需要省略 ref、class 等标签,这对我有用。但我不知道这是否适用于每个标签属性


P
Peter Mortensen

考虑到帖子 JSX In Depth,您可以通过以下方式解决您的问题:

if (isRequired) {
  return (
    <MyOwnInput name="test" required='required' />
  );
}
return (
    <MyOwnInput name="test" />
);

R
Rad

我认为这可能对那些希望属性值成为函数的人有用:

import { RNCamera } from 'react-native-camera';
[...]

export default class MyView extends React.Component {

    _myFunction = (myObject) => {
        console.log(myObject.type); //
    }

    render() {

        var scannerProps = Platform.OS === 'ios' ? 
        {
            onBarCodeRead : this._myFunction
        } 
        : 
        { 
            // here you can add attribute(s) for other platforms
        }

        return (
            // it is just a part of code for MyView's layout
            <RNCamera 
                ref={ref => { this.camera = ref; }}
                style={{ flex: 1, justifyContent: 'flex-end', alignItems: 'center', }}
                type={RNCamera.Constants.Type.back}
                flashMode={RNCamera.Constants.FlashMode.on}
                {...scannerProps}
            />
        );
    }
}

m
malek

以一种简单的方式

const InputText= ({required = false , disabled = false, ...props}) => 
         (<input type="text" disabled={disabled} required={required} {...props} />);

并像这样使用它

<InputText required disabled/>

a
amatinya
<Button {...(isWeb3Enabled ? {} : { isExternal: true })}>
    Metamask
</Button>

T
Tekki Web Solutions Pvt. Ltd.

在 React 中,我们将值作为 Props 从父组件传递到子组件。如果该值为 false,则不会将其作为 props 传递。同样在某些情况下,我们也可以使用三元(条件运算符)。