Jak warunkowo dodać atrybuty do komponentów Reactowych?

Czy istnieje sposób na dodanie atrybutów do komponentu Reactowego tylko wtedy, gdy spełniony jest określony warunek?

Powinienem dodać wymagane i readOnly atrybuty do tworzenia elementów na podstawie wywołania Ajax po renderowaniu, ale nie widzę, jak to rozwiązać, ponieważ readOnly= "false" nie jest tym samym, co całkowite pominięcie atrybutu.

Poniższy przykład powinien wyjaśnić, czego chcę, ale to nie zadziała (błąd Parse: Unexpected identifier).

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" : ""} />
        );
    }
});
Author: Peter Mortensen, 2015-07-01

14 answers

Najwyraźniej w przypadku pewnych atrybutów React jest wystarczająco inteligentny, aby pominąć atrybut, jeśli przekazywana wartość nie jest prawdziwa. Na przykład:

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

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

Spowoduje:

<input type="text" required>

Update: jeśli ktoś jest ciekawy jak/dlaczego tak się dzieje, szczegóły można znaleźć w kodzie źródłowym ReactDOM, a konkretnie w wierszach 30 oraz 167 z DOMProperty.plik js.

 628
Author: Gian Marco Toso,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-09-13 09:35:42

Odpowiedź Juandemarco jest zwykle poprawna, ale tutaj jest inna opcja.

Zbuduj obiekt jak chcesz:

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

if (condition)
  inputProps.disabled = true;

Renderuj z spreadem, opcjonalnie przekazując również inne właściwości.

<input
    value="this is overridden by inputProps"
    {...inputProps}
    onChange={overridesInputProps}
 />
 448
Author: Brigand,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-01-29 01:03:22

Oto przykład użycia Bootstrap's Button via React-Bootstrap (wersja 0.32.4):

var condition = true;

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

W zależności od warunku zostaną zwrócone {bsStyle: 'success'} lub {}. Operator spread rozprzestrzeni następnie Właściwości zwracanego obiektu na komponent Button. W przypadku falsy, ponieważ na zwracanym obiekcie nie istnieją żadne właściwości, nic nie zostanie przekazane do komponentu.


Alternatywny sposób oparty na komentarz Andy ' ego Polhilla :

var condition = true;

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

Jedyną małą różnicą jest to, że w drugim przykładzie wewnętrzny składnik <Button/>'S props obiekt będzie miał klucz bsStyle o wartości undefined.

 364
Author: Arman Yeghiazaryan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-01-29 01:06:05

Oto alternatywa.

var condition = true;

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

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

Lub jego wersja inline

var condition = true;

var component = (
  <div
    value="foo"
    { ...( condition && { disabled: true } ) } />
);
 108
Author: Season,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-01-29 01:09:42

Tak to zrobię.

Z warunkowym :

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

Nadal wolę używać regularnego sposobu przekazywania rekwizytów w dół, ponieważ jest on bardziej czytelny (moim zdaniem) w przypadku nie mają żadnych warunków.

Bez warunku :

<Label text={label} type={type} tooltip={tooltip} isRequired={required} />
 45
Author: Tony Tai Nguyen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-01-29 01:20:00

Powiedzmy, że chcemy dodać właściwość niestandardową (używając aria - * lub data -*), jeśli warunek jest prawdziwy:

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

Powiedzmy, że chcemy dodać właściwość stylu, jeśli warunek jest prawdziwy:

{...this.props.isTrue && {style : {color: 'red'}}}
 27
Author: Mina Luke,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-01-29 01:11:28

Możesz użyć tego samego skrótu, który służy do dodawania/usuwania (części) komponentów ({isVisible && <SomeComponent />}).

class MyComponent extends React.Component {
  render() {
    return (
      <div someAttribute={someCondition && someValue} />
    );
  }
}
 20
Author: GijsjanB,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-10-24 14:49:12

Jeśli używasz ECMAScript 6, możesz po prostu napisać tak.

// First, create a wrap object.
const wrap = {
    [variableName]: true
}
// Then, use it
<SomeComponent {...{wrap}} />
 13
Author: snyh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-01-29 01:12:43

To powinno zadziałać, ponieważ twój stan zmieni się po wywołaniu Ajax, a komponent macierzysty ponownie wyrenderuje.

render : function () {
    var item;
    if (this.state.isRequired) {
        item = <MyOwnInput attribute={'whatever'} />
    } else {
        item = <MyOwnInput />
    }
    return (
        <div>
            {item}
        </div>
    );
}
 8
Author: Michael Parker,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-01-29 00:59:37

W Reaccie możesz warunkowo renderować komponenty, ale także ich atrybuty, takie jak props, className, id i inne.

W Reaccie bardzo dobrą praktyką jest używanie operatora ternary , który może pomóc w warunkowym renderowaniu komponentów.

Przykład pokazuje również, jak warunkowo renderować komponent i jego atrybut stylu.

Oto prosty przykład:

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>
 3
Author: Juraj,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-01-29 01:18:32

Na przykład Używanie stylów właściwości dla niestandardowego kontenera

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

  return (
    <Container {...otherProps} >
 2
Author: Jonas Sciangula Street,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-08-12 15:30:33

Rozważając post JSX w głębi, możesz rozwiązać swój problem w ten sposób:

if (isRequired) {
  return (
    <MyOwnInput name="test" required='required' />
  );
}
return (
    <MyOwnInput name="test" />
);
 0
Author: Viktor Kireev,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-01-29 01:01:18

Z mojego punktu widzenia najlepszym sposobem zarządzania wieloma rekwizytami warunkowymi jest props object podejście @brigand. Ale można go poprawić, aby uniknąć dodawania jednego if bloku dla każdego warunkowego propa.

Pomocnik ifVal

Zmień nazwę jak chcesz (iv, condVal, CV,_,...)

Możesz zdefiniować funkcję pomocniczą, która zwróci wartość, lub inną, jeśli spełniony jest warunek:

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

If cond is true (or truthy ), the trueValue jest zwracane-lub true. Jeśli cond jest false (lub falsy ), zwraca się falseValue - lub null.

Te wartości domyślne (true i null) są zazwyczaj wartościami pozwalającymi na przekazanie właściwości do komponentu Reactowego. Możesz myśleć o tej funkcji jako o "ulepszonym operatorze trójdzielnym Reacta". Popraw go, jeśli potrzebujesz większej kontroli nad zwracanymi wartościami.

Użyjmy go z wieloma rekwizytami.

Zbuduj obiekt (złożony) props

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

To podejście jest podobne do popularnego sposobu warunkowego zarządzania klasami za pomocą narzędzia classnames , ale dostosowane do właściwości.

Dlaczego warto stosować to podejście

Będziesz miał czystą i czytelną składnię, nawet z wieloma rekwizytami warunkowymi: każdy nowy rekwizytor wystarczy dodać wiersz kodu wewnątrz deklaracji obiektu.

W ten sposób zamieniasz szum składniowy powtarzających się operatorów (..., &&, ? :, ...), które mogą być bardzo irytujące, gdy masz wiele rekwizytów, z prostym wywołaniem funkcji.

Naszym priorytetem, jako programistów, jest napisanie najbardziej oczywistego kodu, który rozwiąże problem. Zbyt wiele razy rozwiązujemy problemy dla naszego ego , dodając złożoności tam, gdzie nie jest to wymagane. Nasz Kodeks powinien być prosty, dla nas dzisiaj, dla nas jutro i dla naszych kolegów.

To, że możemy coś zrobić, nie znaczy, że powinniśmy.]}

Mam nadzieję, że ta późna odpowiedź pomoże.

 0
Author: lifeisfoo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-11-23 09:40:53

Myślę, że może to być przydatne dla tych, którzy chcieliby, aby wartość atrybutu była funkcją:

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}
            />
        );
    }
}
 0
Author: Radosław Rudnicki,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2021-01-14 10:56:25