Atributo dinâmico no ReactJS

92

Eu quero incluir / omitir dinamicamente o atributo disabled em um elemento de botão. Já vi muitos exemplos de valores de atributos dinâmicos, mas não dos próprios atributos. Tenho a seguinte função de renderização:

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

Isso gera um erro de análise por causa do caractere "{". Como posso incluir / omitir o atributo desativado com base no resultado (booleano) de AppStore.cartIsEmpty ()?

Timmy
fonte

Respostas:

167

A maneira mais limpa de adicionar atributos opcionais (incluindo disablede outros que você pode querer usar) é usar atributos de propagação 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'));

Usando atributos de propagação, você pode adicionar dinamicamente (ou substituir) quaisquer atributos que desejar usando uma instância de objeto javascript. No meu exemplo acima, o código cria uma disabledchave (com um disabledvalor neste caso) quando a disabledpropriedade é passada para a Helloinstância do componente.

Se você deseja apenas usar disabled, esta resposta funciona bem.

WiredPrairie
fonte
Uma vez instalado, o CSS: a[disabled] { pointer-events: none; }irá parar as ações em um elemento / componente
timbó
49

Você pode passar um booleano para o disabledatributo.

render: function() {
    return <button disabled={AppStore.cartIsEmpty()}>Clear cart</button>
}
Alexandre Kirszenberg
fonte
8
não, você não pode. a presença do atributo disabled desativa o botão completamente. consulte http://jsfiddle.net/ttjhyvmt/
Timmy
20
React é inteligente o suficiente para definir condicionalmente o disabledatributo no HTML resultante, dependendo do valor que você passou jsfiddle.net/kb3gN/10379
Alexandre Kirszenberg
2
não sei como perdi isso, obrigado! embora funcione para o meu caso específico, aceitei outra resposta que omite / inclui atributos
Timmy
1
Tive problemas com o IE11, no entanto, não estávamos usando a reação mais recente. A resposta de atributos de propagação JSX funcionou.
LessQuesar
24

Estou usando o React 16 e isso funciona para mim (onde boolestá o seu teste):

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

Basicamente, com base em test ( bool), você retorna um objeto com o atributo ou retorna um objeto vazio.

Além disso, se você precisar adicionar ou omitir vários atributos, poderá fazer o seguinte:

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

Para atributos gerenciados mais elaborados, sugiro que você pré-fabricar o objeto com (ou sem) os atributos fora do JSX.

Lucas
fonte
Obrigado por essa resposta simples, mas muito útil!
tommygun
4

Uma maneira mais limpa de fazer atributos dinâmicos que funciona para qualquer atributo é

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

Chame seu componente de reação como seguir

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

Dicas:

  1. Você poderia ter dynamicAttributesfunção em um local / utilitários comum e importá-lo para usá-lo em todos os componentes

  2. você poderia passar valor nullpara não renderizar o atributo dinâmico

Venkat Reddy
fonte
Por que não fazer assim: <ReactComponent {... {"data-url": dataURL}} />? é mais simples e nenhum "dynamicAttributes" necessário
gdbdable
No caso do atributo ser nulo, não queremos reagir para renderizar esse atributo. exemplo: "data-modal": null não queremos reagir para mostrar data-model = "null". neste caso, meu código acima nem mesmo mostrará o atributo, ou seja, o atributo dinâmico com base no valor.
Venkat Reddy
2

Você pode encontrar algo semelhante a isso na documentação.

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

No seu caso poderia ser algo assim

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

Este código está usando ES6, mas acho que você teve a ideia.

Isso é legal porque você pode passar muitos outros atributos para este componente e ainda funcionará.

usuário3552712
fonte
2

A versão que usei foi:

<button disabled={disabled ? 'disabled' : undefined}>
    Click me (or dont)
</button>
AnilRedshift
fonte
É uma má prática usar undefined em seu código. Também é desnecessário, pois você pode simplesmente escrever <button disabled = {disabled}>, pois disabled é uma variável booleana que retorna verdadeiro ou falso
Raphael Pinel
Por que é uma má prática indefinida? Citação, se possível. Também, talvez, o Reagir manipule corretamente os bools agora, mas no momento em que escrevemos sua sugestão não funcionaria corretamente
AnilRedshift
2

Uma maneira simples e limpa de fazer isso

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

desativado deve vir de suportes como este

<MyComponent disabled />
Yogiyo
fonte
1

Muito mais limpa do que a solução aceita é a solução que o AnilRedshift mencionou, mas que irei expandir.

Simplificando, os atributos HTML têm um nome e um valor. Como abreviação, você pode usar o nome apenas para "desativado", "múltiplo", etc. Mas a versão extensa ainda funciona e permite que o React funcione de sua maneira preferida.

disabled={disabled ? 'disabled' : undefined} é a solução mais legível.

jhchnc
fonte
0

Primeiro você pode simplesmente verificar

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

Nota: ** o valor desativado não é String, deve ser Booleano .

Agora para dinâmica. Você pode simplesmente escrever

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

Como você pode ver, estou usando a propriedade disabled e, entre chaves, pode ser variável local / var de estado. A variável disablecontém valores verdadeiro / falso.

vinayak lakhotiya
fonte
-3

Isso pode funcionar, o problema com desativado é que não se pode simplesmente definir o booleano para ele.

if(AppStore.cartIsEmpty()){
  return "<button disabled>Clear cart</button>"
}
else
{
  return "<button>Clear cart</button>"
}
IcyBright
fonte
Eu estava com medo de ter que recorrer a isso .. Vou esperar para ver se mais alguém tem alguma sugestão antes de aceitar sua resposta
Timmy