Reactjs setState () com um nome de chave dinâmico?

248

EDIT: esta é uma duplicata, veja aqui

Não consigo encontrar exemplos de como usar um nome de chave dinâmica ao definir o estado. Isto é o que eu quero fazer:

inputChangeHandler : function (event) {
    this.setState( { event.target.id  : event.target.value } );
},

onde event.target.id é usado como a chave de estado a ser atualizada. Isso não é possível no React?

trad
fonte
4
Esta é uma duplicata de qualquer pergunta sobre chaves de objetos dinâmicos. Não é específico para reagir
Cory Danielson
9
var newstate = {}; newstate [event.target.id] = event.target.id; this.setState (newstate);
Cory Danielson
Obrigado, eu não sabia muito bem como usar objetos em geral.
trad
@trad Estou com esse problema, mas o que você colocou no seu estado inicial? Não importa, certo?
Raphael Onofre

Respostas:

280

Graças à dica de @ Cory, usei isso:

inputChangeHandler : function (event) {
    var stateObject = function() {
      returnObj = {};
      returnObj[this.target.id] = this.target.value;
         return returnObj;
    }.bind(event)();

    this.setState( stateObject );    
},

Se você estiver usando o ES6 ou o transpiler Babel para transformar seu código JSX, também poderá fazer isso com nomes de propriedades calculados :

inputChangeHandler : function (event) {
    this.setState({ [event.target.id]: event.target.value });
    // alternatively using template strings for strings
    // this.setState({ [`key${event.target.id}`]: event.target.value });
}
trad
fonte
27
Há também uma nova sintaxe para isso, se você estiver usando o bablejs para criar seu código. Você pode usarcomputed property names
Cory Danielson
A segunda abordagem causa erro de sintaxe nos navegadores do Windows (IE, Chrome). Alguém notou?
Benjaminz
como se declarar?
Muneem Habib
Obrigado trad, é isso que eu estava procurando para evitar a duplicação de código para <Radio />implementação.
Adesh H
6
Se você definir um estado usando o nome da propriedade computada como este: this.setState({ [event.target.id]: event.target.value });como você acessaria esse estado usando this.state......?
user3574492
142

Quando você precisar manipular vários elementos de entrada controlados, poderá adicionar um atributo de nome a cada elemento e deixar a função do manipulador escolher o que fazer com base no valor de event.target.name.

Por exemplo:

inputChangeHandler(event) {
  this.setState({ [event.target.name]: event.target.value });
}

vikram jeet singh
fonte
7
o que os colchetes em torno de [event.target.name] indicam? Por que eles são necessários?
User798719
1
Em comparação com a abordagem usual de nomear cada elemento separadamente como this.setState ({userName: e.target.value}); Isso manipulará vários elementos do formulário como uma matriz e não será necessário definir cada elemento individual
vikram jeet singh
1
mas ainda como faço para acessar esse estado da mesma maneira? gosta this.state([event.target.name])?
Kirankumar Dafda 30/08/19
1
Acho que os documentos da Web MDN e este post explicam por que precisamos dos colchetes.
Kelli
46

Como eu consegui isso ...

inputChangeHandler: function(event) {
  var key = event.target.id
  var val = event.target.value
  var obj  = {}
  obj[key] = val
  this.setState(obj)
},
sintaxi
fonte
Fiz da mesma maneira, mas o problema era que ainda não renderizava o componente e corri o pilar para publicar (incluindo este: D), e em algum lugar encontrei o seguinte: o this.forceUpdate();que não deveria ter sido o caso do React mais recente. Vamos ver qual é o problema mais tarde !!
Xploreraj
24

Eu só queria acrescentar que você também pode usar a desestruturação para refatorar o código e torná-lo mais limpo.

inputChangeHandler: function ({ target: { id, value }) {
    this.setState({ [id]: value });
},
saulable
fonte
10

Em loop com .maptrabalhos como este:

{
    dataForm.map(({ id, placeholder, type }) => {
        return <Input
            value={this.state.type}
            onChangeText={(text) => this.setState({ [type]: text })}
            placeholder={placeholder}
            key={id} />
    })
}

Observe o parâmetro []in type. Espero que isto ajude :)

Johnatan Maciel
fonte
10

Eu tive um problema parecido.

Eu queria definir o estado em que a chave do segundo nível estava armazenada em uma variável.

por exemplo this.setState({permissions[perm.code]: e.target.checked})

No entanto, isso não é uma sintaxe válida.

Eu usei o seguinte código para conseguir isso:

this.setState({
  permissions: {
    ...this.state.permissions,
    [perm.code]: e.target.checked
  }
});
Matthew Holtom
fonte
4

Com o ES6 +, você pode fazer [ ${variable}]

Jujhar Singh
fonte
2

Eu estava procurando uma solução bonita e simples e achei o seguinte:

this.setState({ [`image${i}`]: image })

Espero que isto ajude

Catalina
fonte
1
this.setState({ [`${event.target.id}`]: event.target.value}, () => {
      console.log("State updated: ", JSON.stringify(this.state[event.target.id]));
    });

Por favor, observe o caractere de citação.

Javatar
fonte
0

Seu estado com o dicionário atualiza alguma chave sem perder outro valor

state = 
{   
    name:"mjpatel"  
    parsedFilter:
    {
      page:2,
      perPage:4,
      totalPages: 50,
    }
}

A solução está abaixo

 let { parsedFilter } = this.state
 this.setState({
      parsedFilter: {
        ...this.state.parsedFilter,
        page: 5
      }
  });

aqui atualize o valor da chave "página" com o valor 5

manoj patel
fonte
-4

Pode usar uma sintaxe de propagação, algo como isto:

inputChangeHandler : function (event) {
    this.setState( { 
        ...this.state,
        [event.target.id]: event.target.value
    } );
},
sta
fonte
7
O React fará com que o objeto seja mesclado para você, isso é uma prática ruim.
Rohmer
1
basicamente, se você tem algum objeto interno e deseja alterar uma propriedade desse objeto interno, é assim: this.setState ({selectedItems: {... selectedItems: {... selectedItems, [item.id]: true}})
Eran Ou