Reactjs setState () avec un nom de clé dynamique?

248

EDIT: ceci est un doublon, voir ici

Je ne trouve aucun exemple d'utilisation d'un nom de clé dynamique lors de la définition de l'état. Voici ce que je veux faire:

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

où event.target.id est utilisé comme clé d'état à mettre à jour. N'est-ce pas possible dans React?

trad
la source
4
Il s'agit d'un double de toute question concernant les clés d'objets dynamiques. Ce n'est pas spécifique de réagir
Cory Danielson
9
var newstate = {}; newstate [event.target.id] = event.target.id; this.setState (newstate);
Cory Danielson
Merci, je n'avais pas une bonne maîtrise de l'utilisation des objets en général.
trad
@trad Je suis avec ce problème mais, qu'avez-vous mis sur votre état initial? Ce n'est pas grave, non?
Raphael Onofre

Réponses:

280

Grâce à l'indice de @ Cory, j'ai utilisé ceci:

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

    this.setState( stateObject );    
},

Si vous utilisez ES6 ou le transpilateur Babel pour transformer votre code JSX, vous pouvez également effectuer cela avec des noms de propriété calculés :

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
la source
27
Il y a aussi une nouvelle syntaxe pour cela, si vous utilisez bablejs pour construire votre code. Vous pouvez utilisercomputed property names
Cory Danielson
La deuxième approche provoque une erreur de syntaxe dans les navigateurs sur Windows (IE, Chrome). Quelqu'un l'a-t-il remarqué?
benjaminz
comment se déclarer?
Muneem Habib
Merci trad, c'est ce que je cherchais pour éviter la duplication de code pour l' <Radio />implémentation.
Adesh M
6
Si vous définissez un état en utilisant le nom de propriété calculé comme ceci: this.setState({ [event.target.id]: event.target.value });alors comment accéderiez-vous à cet état en utilisant this.state......?
user3574492
142

Lorsque vous devez gérer plusieurs éléments d'entrée contrôlés, vous pouvez ajouter un attribut de nom à chaque élément et laisser la fonction de gestionnaire choisir quoi faire en fonction de la valeur de event.target.name.

Par exemple:

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

vikram jeet singh
la source
7
qu'indiquent les crochets autour de [event.target.name]? Pourquoi sont-ils nécessaires?
user798719
1
Par rapport à l'approche habituelle pour nommer chaque élément séparément comme this.setState ({userName: e.target.value}); Cela gérera plusieurs éléments de forme comme un tableau et pas besoin de définir chaque élément individuel
vikram jeet singh
1
mais comment accéder à cet état de la même manière? comme this.state([event.target.name])?
Kirankumar Dafda
1
Je pense que les documents Web MDN et cet article expliquent pourquoi nous avons besoin des supports.
Kelli
46

Comment j'ai accompli cela ...

inputChangeHandler: function(event) {
  var key = event.target.id
  var val = event.target.value
  var obj  = {}
  obj[key] = val
  this.setState(obj)
},
sintaxi
la source
J'ai fait de même, mais le problème était qu'il ne rendait toujours pas le composant, et j'ai couru pilier pour poster (y compris ceci: D), et quelque part trouvé ceci: ce this.forceUpdate();qui n'aurait pas dû être le cas avec la dernière React. Voyons quel est le problème plus tard !!
xploreraj
24

Je voulais juste ajouter que vous pouvez également utiliser la déstructuration pour refactoriser le code et le rendre plus net.

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

En boucle avec un .maptravail comme celui-ci:

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

Notez le paramètre []in type. J'espère que cela t'aides :)

Johnatan Maciel
la source
10

J'avais un problème similaire.

Je voulais définir l'état de stockage de la clé de 2e niveau dans une variable.

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

Cependant, ce n'est pas une syntaxe valide.

J'ai utilisé le code suivant pour y parvenir:

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

Avec ES6 +, vous pouvez simplement faire [ ${variable}]

Jujhar Singh
la source
2

Je cherchais une solution jolie et simple et j'ai trouvé ceci:

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

J'espère que cela t'aides

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

Veuillez noter le caractère de citation.

Javatar
la source
0

Votre état avec dictionnaire met à jour une clé sans perdre d'autre valeur

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

La solution est ci-dessous

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

ici mettre à jour la valeur de la "page" clé avec la valeur 5

manoj patel
la source
-4

Peut utiliser une syntaxe étendue, quelque chose comme ceci:

inputChangeHandler : function (event) {
    this.setState( { 
        ...this.state,
        [event.target.id]: event.target.value
    } );
},
sta
la source
7
React fera fusionner l'objet pour vous, c'est une mauvaise pratique.
Rohmer
1
Fondamentalement, si vous avez un objet interne et que vous souhaitez modifier une propriété sur cet objet interne, vous le faites comme ceci: this.setState ({selectedItems: {... selectedItems, [item.id]: true}})
Eran Or