Reactjs setState () con un nome chiave dinamico?


248

EDIT: questo è un duplicato, vedi qui

Non riesco a trovare alcun esempio di utilizzo di un nome chiave dinamico quando si imposta lo stato. Questo è quello che voglio fare:

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

dove event.target.id viene utilizzato come chiave di stato da aggiornare. Questo non è possibile in React?


4
Questo è un duplicato di qualsiasi domanda relativa alle chiavi dinamiche degli oggetti. Non è specifico per reagire
— Cory Danielson,

9
var newstate = {}; newstate [event.target.id] = event.target.id; this.setState (newstate);
— Cory Danielson,

Grazie, non avevo una buona padronanza sull'uso degli oggetti in generale.
— trad


@trad Sono con questo problema ma, cosa hai messo nel tuo stato iniziale? Non importa, vero?
— Raphael Onofre,

Risposte:


280

Grazie al suggerimento di @ Cory, ho usato questo:

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

    this.setState( stateObject );    
},

Se usi ES6 o il transpiler Babel per trasformare il tuo codice JSX, puoi farlo anche con nomi di proprietà calcolati :

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

27
C'è anche una nuova sintassi per questo, se stai usando bablejs per costruire il tuo codice. Puoi usarecomputed property names
— Cory Danielson il

Il secondo approccio provoca errori di sintassi nei browser su Windows (IE, Chrome). Qualcuno l'ha notato?
— Benjaminz,

come farsi dichiarare?
— Muneem Habib,

Grazie trad, questo è quello che stavo cercando per evitare la duplicazione del codice per l' <Radio />implementazione.
— Adesh M

6
Se imposti uno stato utilizzando il nome della proprietà calcolata in questo modo: this.setState({ [event.target.id]: event.target.value });come accederesti a tale stato this.state......?
— user3574492

142

Quando è necessario gestire più elementi di input controllati, è possibile aggiungere un attributo name a ciascun elemento e lasciare che la funzione handler scelga cosa fare in base al valore di event.target.name.

Per esempio:

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


7
cosa indicano le parentesi intorno a [event.target.name]? Perché sono richiesti?
— user798719

1
Rispetto al solito approccio per nominare ciascun elemento separatamente come this.setState ({userName: e.target.value}); Questo gestirà più elementi del modulo come un array e non è necessario impostare ogni singolo elemento
— vikram jeet singh

1
ma come posso accedere a quello stato allo stesso modo? come this.state([event.target.name])?
— Kirankumar Dafda,

1
Penso che i documenti web MDN e questo post spieghino perché abbiamo bisogno delle parentesi.
— Kelli

46

Come ho realizzato questo ...

inputChangeHandler: function(event) {
  var key = event.target.id
  var val = event.target.value
  var obj  = {}
  obj[key] = val
  this.setState(obj)
},

Ho fatto lo stesso modo, ma il problema era che non rendevo ancora il componente e ho eseguito il pilastro per pubblicare (incluso questo: D), e da qualche parte this.forceUpdate();ho trovato questo: che non avrebbe dovuto essere il caso dell'ultimo React. Vediamo qual è il problema più tardi !!
— xploreraj,

24

Volevo solo aggiungere che puoi anche usare la destrutturazione per riformattare il codice e renderlo più ordinato.

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

10

In loop con .maplavoro come questo:

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

Si noti la []di typeparametro. Spero che questo ti aiuti :)


10

Ho avuto un problema simile.

Volevo impostare lo stato in cui era memorizzata la chiave di 2 ° livello in una variabile.

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

Tuttavia questa non è sintassi valida.

Ho usato il seguente codice per raggiungere questo obiettivo:

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


2

Stavo cercando una soluzione carina e semplice e ho trovato questo:

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

Spero che questo ti aiuti


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

Si prega di tenere presente il carattere di citazione.


0

Il tuo stato con dizionario aggiorna alcune chiavi senza perdere altro valore

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

La soluzione è sotto

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

qui aggiorna il valore per la chiave "pagina" con il valore 5


-4

Può usare una sintassi diffusa, qualcosa del genere:

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

7
React farà l'oggetto fondendosi per te, questa è una cattiva pratica.
— Rohmer,

1
fondamentalmente se hai qualche oggetto interno e vuoi cambiarne uno proprio su quell'oggetto interno, lo fai in questo modo: this.setState ({selectedItems: {... selectedItems, [item.id]: true}})
— Eran Or
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.