web-dev-qa-db-fra.com

Comment passer une valeur d'objet dans le champ de sélection d'un formulaire onChange (en utilisant React, sans Redux)

Je travaille actuellement sur un composant react avec une forme simple (pas de redux, juste en utilisant react-bootstrap pour le styling)

Je extrait des données d'une base de données sous la forme suivante:

[
  {
    "id":"123",
    "name":"Amy Pond",
    "age":"22",
    "reputation":22000
  },
  {
    "id":"124",
    "name":"Clara Oswald",
    "age":"24",
    "reputation":35000
 }
 ...
]

et le mettre dans un objet:

let userlist = [];
userlist = addUsers(this.state.users);

J'ai utilisé map pour créer un menu déroulant basé sur ces données et je peux définir correctement l'état de l'utilisateur sur celui sélectionné dans le menu déroulant: 

<FormControl
   id = "user"
   componentClass="select"
   onChange={this.handleChange}
>
   {userlist.map((r , i) =>
     <option
       key={i}
       value={r.name}>
       {r.name}
     </option>
  )}
</FormControl>

en utilisant handleChange ()

handleChange(event) {
  this.setState({
    value: event.target.value,
    // reputation: ???? // here's where I'm running into issues
    // age: ???????  // and here
});

Mon problème est que j'ai besoin de l'âge et de la réputation de l'utilisateur dans la fonction handleChange pour définir leurs états en conséquence. J'ai essayé de passer juste r au lieu de r.name mais je récupère [object Object]

console.log ("Handle Change Value: " + event.target.value);

si j'essaie event.target.value.name, je récupère undefined

La seule chose qui a fonctionné jusqu’à présent, est d’utiliser JSON.stringify, mais j’ai l’impression que ce n’est pas la bonne façon de procéder. J'ai aussi pensé à chercher dans les objets une fois que j'ai reçu le nom, mais s'il y avait beaucoup d'objets, je pense que ce serait extrêmement inefficace? Je ne sais pas non plus comment faire cela.

Quelqu'un peut-il m'aider à trouver un moyen de passer ces deux valeurs supplémentaires afin de pouvoir définir l'état? La carte est-elle même le meilleur moyen de créer les options? Honnêtement, j’ai l’impression que c’est une chose si simple, mais je suis encore novice et j’ai du mal à le faire depuis trop longtemps! 

Toutes les idées/modifications/commentaires/moyens d'améliorer cela seraient très appréciés! Je me rends compte que l’utilisation de quelque chose comme redux-form faciliterait cela, mais j’espère qu’il existe un moyen simple de le faire sans cela pour le moment. 

Edit: OnChange aurait dû être défini sur onChange = {this.handleChange}, juste collé le mauvais code de mes tentatives de dépannage. Je lie ceci dans le constructeur: 

constructor(props) {
  super(props);
  ...
  this.handleChange = this.handleChange.bind(this);
}
5
RatKing

Utilisez l'ID utilisateur comme valeur dans chaque option, puis dans handleChange, recherchez l'utilisateur dans votre userlist pour accéder à toutes ses propriétés:

<FormControl
   id = "user"
   componentClass="select"
   onChange={this.handleChange.bind(this)}
>
   {userlist.map((r , i) =>
     <option
       key={i}
       value={r.id}>
       {r.name}
     </option>
  )}
</FormControl>

handleChange(event) {
  const userId = event.target.value;
  const user = userlist.find(u => u.id === userId);
  this.setState({
    value: user
  });
}

La manière dont vous passez la propriété onChange peut également causer des problèmes. Il est difficile de dire sans voir tout votre code, mais assurez-vous de passer une référence à votre fonction handleChange (voir ci-dessus dans ma réponse) plutôt que de l'appeler ici (comme dans votre question: onChange={this.handleChange()}, à moins que votre fonction this.handleChange ne renvoie un une fonction).

4
forrert

Cela pourrait être un problème avec la façon dont vous avez défini votre écouteur d'événement. Les paramètres onChange={this.handleChange()} provoqueraient le déclenchement immédiat de l'écouteur. Utiliser onChange={this.handleChange} définit correctement le programme d'écoute. 

<FormControl
   id = "user"
   componentClass="select"
   onChange={this.handleChange}>
   {userlist.map((r , i) =>
     <option
       key={i}
       value={r.name}>
       {r.name}
     </option>
  )}
</FormControl>

Voir ici pour plus d'informations sur les événements. 

Vous pouvez ensuite utiliser find() dans votre gestionnaire d'événements pour localiser l'utilisateur:

handleChange(event) {
  let user = users.find(u => u.name === event.user.name);
  this.setState({user: user});
}
1
Sinan Guclu

vous pouvez utiliser option tag attribut et json pour encoder/décoder de la manière suivante:

<FormControl
        id="user"
        componentClass="select"
        onChange={this.handleChange.bind(this)}
    >
        {userlist.map((r, i) =>
            <option
                key={i}
                value={r.id}>
                {r.name}
                data={JSON.stringify(r)}
            </option>
        )}
    </FormControl>;

    handleChange(event)
    {
        if (e.target.options && e.target.selectedIndex) {
            const user = e.target.options[e.target.selectedIndex].getAttribute('data');
            this.setState({
                value: user
            });
        }
    }
0
Mahdi Hasanpour