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

时间:2015-07-01 14:07:27

标签: javascript reactjs

如果满足某个条件,是否只能向React组件添加属性?

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

以下示例应该解释我想要的内容,但不会工作(解析错误:意外的标识符)。

var React = require('React');

var MyOwnInput = React.createClass({
    render: function () {
        return (
            <div>
                <input type="text" onChange={this.changeValue} value={this.getValue()} name={this.props.name}/>
            </div>
        );
    }
});

module.exports = React.createClass({
    getInitialState: function () {
        return {
            isRequired: false
        }
    },
    componentDidMount: function () {
        this.setState({
            isRequired: true
        });
    },
    render: function () {
        var isRequired = this.state.isRequired;

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

16 个答案:

答案 0 :(得分:382)

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

var InputComponent = React.createClass({
    render: function() {
        var required = true;
        var disabled = false;

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

将导致:

<input type="text" required data-reactid=".0.0">

答案 1 :(得分:294)

只是抛出另一个选项,但 @ juandemarco的答案通常是正确的。

按照自己喜欢的方式构建对象:

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

if (condition) inputProps.disabled = true;

使用展开渲染,也可以选择传递其他道具。

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

答案 2 :(得分:200)

以下是通过Bootstrap使用Button&#39; s React-Bootstrap的示例。

var condition = true;

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

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

基于@Andy Polhill评论的替代方式:

var condition = true;

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

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

答案 3 :(得分:55)

晚会。这是另一种选择。

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

答案 4 :(得分:14)

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

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

答案 5 :(得分:13)

这是我的一种方式。

使用条件

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

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

无条件

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

答案 6 :(得分:8)

晚会。

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

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

假设我们想要在条件为真时添加样式属性:

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

答案 7 :(得分:6)

如果你使用es6,你可以这样写。

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

答案 8 :(得分:4)

这应该有效,因为在ajax调用之后你的状态会改变,而且父组件会重新渲染。

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

答案 9 :(得分:1)

例如将属性样式用于自定义容器

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

  return (
    <Container {...otherProps} >

答案 10 :(得分:0)

考虑到这篇文章https://facebook.github.io/react/tips/if-else-in-JSX.html,您可以通过这种方式解决问题

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

答案 11 :(得分:0)

在React中,您可以有条件地呈现组件,还可以呈现其属性,如props,className,id等。

在React中,使用&#34; Ternary运算符&#34;是非常好的做法。哪个可以帮到你 有条件地渲染组件。

示例还显示了如何有条件地呈现Component及其样式属性

这是一个简单的例子:

&#13;
&#13;
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"));
&#13;
<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>
&#13;
&#13;
&#13;

答案 12 :(得分:0)

从我的角度来看,管理多个条件道具的最佳方法是@brigand的 props对象方法。但是可以进行改进,以避免为每个条件道具添加一个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(或 fassy ),则返回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有条件地管理类的流行方法,但适用于道具。

为什么要使用这种方法

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

通过这种方式,您可以替换重复运算符(...&&? :等的语法噪声,这可能会很烦人当您有许多道具时,只需调用一个简单的函数即可。

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

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

我希望这个较晚的答复会有所帮助。

答案 13 :(得分:0)

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

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

答案 14 :(得分:0)

我希望你觉得这很有用。 您可以使用三元运算符和布尔值有条件地添加只读属性。 下面给出的是启用文本输入的 React 类组件的示例,前提是用户勾选了复选框输入。

  class Input extends React.Component{
       constructor(props){
          super(props)
       this.state={ checkbox: false}
       this.handleCheckbox=this.handleCheckbox.bind(this);

    }
  handleCheckbox(){
     this.setState({checkbox: true})
   }

   render(){

 const{checkbox}=this.state;

  return (
      <div>
            <input onChange={this.handleCheckbox} type="checkbox" />
            <label htmlFor="pets">Do you have pets? If Yes, 
            please tick mark & enter their names below and provide at least two 
            names.</label>
  
       <div>
         <input  type="text" disabled={!checkbox ?true : false} required={true}/>
         <input  type="text" disabled={!checkbox ?true : false} required={true}/>
         <input  type="text" disabled={!checkbox ?true : false} required={false}/>
      </div>
   </div>
   );
  }
 }

这将在 DOM 中进行更改。 此外,您可以为文本类型输入创建一个单独的子组件,并将复选框输入的状态传递给它。

答案 15 :(得分:0)

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

const name = "someName";

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