Dynamiczny atrybut w ReactJS


93

Chcę dynamicznie dołączać / pomijać wyłączony atrybut w elemencie przycisku. Widziałem wiele przykładów dynamicznych wartości atrybutów, ale nie samych atrybutów. Mam następującą funkcję renderowania:

render: function() {
    var maybeDisabled = AppStore.cartIsEmpty() ? "disabled" : "";
    return <button {maybeDisabled}>Clear cart</button>
}

Powoduje to błąd analizy z powodu znaku „{”. Jak mogę dołączyć / pominąć wyłączony atrybut na podstawie (boolean) wyniku AppStore.cartIsEmpty ()?

Odpowiedzi:


171

Najczystszym sposobem dodawania atrybutów opcjonalnych (w tym disabledi innych, których możesz chcieć użyć) jest obecnie użycie atrybutów rozszerzania JSX :

var Hello = React.createClass({
    render: function() {
        var opts = {};
        if (this.props.disabled) {
            opts['disabled'] = 'disabled';
        }
        return <button {...opts}>Hello {this.props.name}</button>;
    }
});

React.render((<div><Hello name="Disabled" disabled='true' />
    <Hello name="Enabled"  />
</div>)
, document.getElementById('container'));

Używając atrybutów rozszerzania, możesz dynamicznie dodawać (lub nadpisywać) dowolne atrybuty, korzystając z instancji obiektu javascript. W powyższym przykładzie kod tworzy disabledklucz (z disabledwartością w tym przypadku), gdy disabledwłaściwość jest przekazywana do Helloinstancji składnika.

Jeśli jednak chcesz tylko użyć disabled, ta odpowiedź działa dobrze.


Gdy już na miejscu, CSS takie jak: a[disabled] { pointer-events: none; }zatrzyma działania na elemencie / komponencie
timbo

49

Do disabledatrybutu można przekazać wartość logiczną .

render: function() {
    return <button disabled={AppStore.cartIsEmpty()}>Clear cart</button>
}

8
nie, nie możesz. obecność wyłączonego atrybutu całkowicie wyłącza przycisk. patrz http://jsfiddle.net/ttjhyvmt/
Timmy

20
React jest wystarczająco sprytny, aby warunkowo ustawić disabledatrybut w wynikowym kodzie
Alexandre Kirszenberg

2
nie wiem, jak to przegapiłem, dziękuję! chociaż działa to w moim konkretnym przypadku, zaakceptowałem inną odpowiedź, która pomija / zawiera atrybuty
Timmy

1
Mieliśmy problemy z IE11, jednak nie korzystaliśmy z najnowszej reakcji. Odpowiedź dotycząca atrybutów rozprzestrzeniania się JSX zadziałała.
LessQuesar

24

Używam React 16 i to działa dla mnie (gdzie booljest twój test):

<fieldset {...(bool ? {disabled:true} : {})}>

Zasadniczo na podstawie testu ( bool) zwracasz obiekt z atrybutem lub zwracasz pusty obiekt.

Ponadto, jeśli chcesz dodać lub pominąć wiele atrybutów, możesz to zrobić:

<fieldset {...(bool ? {disabled:true} : {})} {...(bool ? {something:'123'} : {})}>

Aby uzyskać bardziej rozbudowane zarządzane atrybuty, sugeruję prefabrykowanie obiektu z atrybutami spoza JSX (lub bez).


Dzięki za tę prostą, ale bardzo pomocną odpowiedź!
tommygun

4

Bardziej przejrzystym sposobem wykonywania atrybutów dynamicznych, który działa dla wszystkich atrybutów, jest

function dynamicAttributes(attribute, value){
  var opts = {};
  if(typeof value !== 'undefined' && value !== null) {
    opts['"'+attribute+'"'] = value;
    return opts;
  }
  return false;
};

Wezwij swój komponent reagowania, jak naśladowanie

<ReactComponent {...dynamicAttributes("disabled",false)}
{...dynamicAttributes("data-url",dataURL)}
{...dynamicAttributes("data-modal",true)} />

Porady:

  1. Możesz mieć dynamicAttributesfunkcję we wspólnym miejscu / narzędziach i zaimportować ją, aby używać jej we wszystkich komponentach

  2. możesz przekazać wartość, nullaby nie renderować atrybutu dynamicznego


Dlaczego nie chcesz tak: <ReactComponent {... {"data-url": dataURL}} />? to prostsze i nie potrzeba żadnych „dynamicAttributes”
gdbdable

W przypadku, gdy atrybut ma wartość null, nie chcemy reagować, aby renderować ten atrybut. przykład: "data-modal": null nie chcemy reagować, aby pokazać data-model = "null". w tym przypadku mój powyższy kod nawet nie pokaże atrybutu, tj. dynamicznego atrybutu opartego na wartości.
Venkat Reddy

3

Znacznie czystsze od przyjętego rozwiązania jest rozwiązanie, o którym wspomniał AnilRedshift, ale które rozwinę.

Mówiąc najprościej, atrybuty HTML mają nazwę i wartość. Krótko mówiąc, możesz użyć nazwy tylko dla „wyłączonych”, „wielokrotnych” itp. Jednak wersja odręczna nadal działa i pozwala Reactowi działać w preferowany sposób.

disabled={disabled ? 'disabled' : undefined} to najbardziej czytelne rozwiązanie.


2

Możesz znaleźć coś podobnego w dokumentacji.

https://facebook.github.io/react/docs/transferring-props.html

W twoim przypadku może być coś takiego

function MyComponent(props) {
    let { disabled, ...attrs } = props;
    if (disabled) {
        // thus, it will has the disabled attribute only if it
        // is disabled
        attrs = {
            ...attrs,
            disabled: true
        }
    };

    return (
        <button {...attrs}>MyLabel</button>
    )
}

Ten kod używa ES6, ale wydaje mi się, że masz pomysł.

To jest fajne, ponieważ możesz przekazać wiele innych atrybutów temu komponentowi i nadal będzie działał.


2

Wersja, której użyłem, to:

<button disabled={disabled ? 'disabled' : undefined}>
    Click me (or dont)
</button>

Używanie undefined w kodzie jest złą praktyką. Jest to również niepotrzebne, ponieważ możesz po prostu napisać <button disabled = {disabled}>, ponieważ disabled jest zmienną logiczną, która zwraca prawdę lub fałsz
Raphael Pinel

Dlaczego niezdefiniowana zła praktyka? Cytowanie, jeśli to możliwe. Być może także zareaguj poprawnie obsługuje teraz bools, ale w momencie pisania twoja sugestia nie zadziała poprawnie
AnilRedshift

2

Prosty i czysty sposób na zrobienie tego

<button {...disabled && {disabled: true}}>Clear cart</button>

wyłączone powinny pochodzić z takich rekwizytów

<MyComponent disabled />

0

Najpierw możesz po prostu sprawdzić

<button disabled={true}>Button 1</button>
<button disabled={false}>Button 2</button>

Uwaga: ** wyłączona wartość nie jest ciągiem, powinna być wartością logiczną .

Teraz dla dynamiki. Możesz po prostu napisać

<button type="button" disabled={disable}  
        onClick={()=>this.setSelectValue('sms')} >{this.state.sms}</button>

Jak widać, używam właściwości wyłączonej iw nawiasach klamrowych może to być zmienna lokalna / zmienna stanu. Zmienna disablezawiera wartości prawda / fałsz.


-3

To może zadziałać, problem z wyłączonymi jest taki, że nie można po prostu ustawić dla niego wartości logicznej.

if(AppStore.cartIsEmpty()){
  return "<button disabled>Clear cart</button>"
}
else
{
  return "<button>Clear cart</button>"
}

Bałem się, że będę musiał uciec się do tego… Poczekam, czy ktoś inny ma jakieś sugestie, zanim przyjmie Twoją odpowiedź
Timmy
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.