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

是否有一种方法可以在满足特定条件的情况下仅向React组件添加属性?

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

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

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

function MyInput({isRequired}) {return <input classname="foo" {isRequired ? "required" : ""} />}
584084 次浏览

这应该可以工作,因为您的状态将在Ajax调用后更改,并且父组件将重新呈现。

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

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

考虑到文章JSX在深度,你可以这样解决你的问题:

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

Juandemarco的回答通常是正确的,但这里有另一个选项。

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

var inputProps = {value: 'foo',onChange: this.handleChange};
if (condition) {inputProps.disabled = true;}

渲染传播,可选地传递其他道具。

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

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

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

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


基于安迪·波尔希尔的评论的替代方法:

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

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

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

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

这里有一个替代方案。

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

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

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

假设我们想要添加一个style属性,如果条件为true:

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

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

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

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

在React中,使用三元算子是非常好的做法,它可以帮助你有条件地渲染组件。

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

这里有一个简单的例子:

class App extends React.Component {state = {isTrue: true};
render() {return (<div>{this.state.isTrue ? (<button style=\{\{ color: this.state.isTrue ? "red" : "blue" }}>I am rendered if TRUE</button>) : (<button>I am rendered if FALSE</button>)}</div>);}}
ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>

我有一个方法。

有条件

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

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

没有条件

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

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

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

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

ifVal助手

重命名你喜欢的(iv, condVal, cv,_,…)

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

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

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

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

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

构建(复杂)props对象

// your-code.jsimport { 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), // truenoProp: ifVal(false), // null - ignored by ReactaProp: 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} />

这种方法类似于使用类名实用程序有条件地管理类的流行方法,但适用于props。

为什么要使用这种方法

您将拥有一个干净易读的语法,即使有许多条件道具:每个新道具只需在对象声明中添加一行代码。

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

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

我们能做些什么并不意味着我们应该做

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

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

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<RNCameraref={ref => { this.camera = ref; }}style=\{\{ flex: 1, justifyContent: 'flex-end', alignItems: 'center', }}type={RNCamera.Constants.Type.back}flashMode={RNCamera.Constants.FlashMode.on}{...scannerProps}/>);}}

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

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

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

<input checked={true} type="checkbox"  />
  1. 对于React[1]列出的一些布尔属性:
<input disabled={disabled} />
// renders either `<input>` or `<input disabled>`
  1. 对于其他属性:
<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

以简单的方式

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

然后像这样使用它

<InputText required disabled/>

在React功能组件中,您可以尝试这样的方法来省略不必要的标记属性。

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

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

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

给定一个局部变量isRequired您可以在渲染方法(如果使用类)或返回语句(如果使用函数组件)中执行以下操作:

 <MyComponent required={isRequired ? 'true' : undefined} />

在这种情况下,如果is的属性是未定义的,false或null(这与添加属性但将其设置为'false'不同),则将添加没有属性。还要注意,我使用字符串而不是布尔值,以避免来自反应的警告消息(在非布尔属性上接收到的布尔值)。

此外,您可以将其他值设置为Boolean

const MyComponent = function() {const Required = "yes";
return (<inputrequired={Required === "yes"}type="text"key={qs.Name}name="DefaultValue"label={qs.QuestionTitle}onChange={(event) => handleInputChange(index, event)}placeholder={qs.QuestionTitle}/>);}

如果是有限数量的财产这将做

function MyInput({isRequired}) {if (isRequired) {return <input classname="foo" isRequired={isRequired} />}return <input classname="foo" />}

如果你有大量的属性,很难为每个属性编写if else条件并相应地返回。为此,你可以将这些属性推送到对象中,并在返回的元素中使用扩展运算符。

    function MyInput({ prop1, prop2, ...propN }) {const props = {};if (prop1) props.prop1 = prop1;...if (propN) props.propN = propN;return <input classname="foo" {...props} />}

您必须将不需要属性时的值设置为未定义示例:

<a data-tooltip={sidebarCollapsed?'Show details':undefined}></a>