繁体   English   中英

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

[英]How do I conditionally add attributes to React components?

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

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

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

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

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

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

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

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

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

if (condition)
  inputProps.disabled = true;

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

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

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

var condition = true;

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

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


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

var condition = true;

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

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

这是一个替代方案。

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

这是我的一种方法。

有条件的

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

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

没有条件

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

假设我们想在条件为真时添加一个自定义属性(使用 aria-* 或 data-*):

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

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

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

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

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

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

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

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

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

在 React 中,你可以有条件地渲染组件,也可以渲染它们的属性,比如 props、className、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>

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

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.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 实用程序有条件地管理类的流行方法,但适用于 props。

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

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

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

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

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

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

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

const name = "someName";

return (
    <input name={name ? name : undefined} />
);
<input checked={true} type="checkbox"  />
<Button {...(isWeb3Enabled ? {} : { isExternal: true })}>
    Metamask
</Button>

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

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

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

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

希望这个对你有帮助。 您可以使用三元运算符和布尔值有条件地添加只读属性。 下面给出的是启用文本输入的 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 中进行更改。 此外,您可以为文本类型输入创建一个单独的子组件,并将复选框输入的状态传递给它。

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

以简单的方式

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

并像那样使用它,如果您希望它是真实的

<InputText required disabled/>
  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

function MyInput({isRequired}) {
 return <input classname="foo" {...(isRequired && { required: true })} />
}

以一种简单的方式

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

并像这样使用它

<InputText required disabled/>

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

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

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

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

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

此外,您可以对Boolean进行其他值

const MyComponent = function() {
    const Required = "yes";

    return (
         <input
                      required={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 条件并相应地返回。 为此,您可以将这些属性推送到 object 中,并在返回的元素中使用扩展运算符。

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM