1
votes

réagir redux de clés en double même lors de la définition d'une clé unique

J'ai un tableau de 6 objets qui ont un uid et rien d'autre. C'est ainsi que je peux répéter sur eux et avoir du contenu d'espace réservé jusqu'à ce qu'un objet soit prêt à être ajouté dans le tableau. J'ai défini une clé unique lorsqu'un nouvel objet est sélectionné. Cependant, si je sélectionne le même objet deux fois, même si je définis une clé unique. Il semble mettre à jour la clé unique sur l'élément dupliqué (même si la clé unique est différente).

Il serait peut-être plus facile de voir le code / l'application en action ici, un exemple du problème serait de cliquer sur squirtle puis sur blastoise, prenez une note des uid affichés. Puis cliquez à nouveau sur squirtle et pour une raison quelconque, il met à jour l'ancien squirtle avec le nouvel uid squirtles provoquant une erreur de clé en double. https://codesandbox.io/s/l75m9z1xwq ou consultez le code ci-dessous. Math.random est juste un espace réservé jusqu'à ce que je puisse faire fonctionner correctement.

const rootReducer = (state = initState, action) => {
  if (action.type === "ADD_POKEMON") {
    let foundFirstEmptyPoke = false;

    const newArray = state.party.map((pokemon, index) => {
      if (typeof pokemon.id === "undefined" && foundFirstEmptyPoke === false) {
        foundFirstEmptyPoke = true;
        pokemon = action.payload; // set the data to the first object that ios empty
      }
      // if we get to the last pokemon and it's not empty
      if (index === 5 && foundFirstEmptyPoke === false) {
        pokemon = action.payload; // replace the last pokemon with the new one
      }
      return pokemon;
    });
    return {
      party: newArray
    };
  }
  return state;
};

Lorsque je clique sur quelque chose, cela se déclenche:

handleClick = pokemon => {
   // setup a uid, will need a better method than math.random later
   pokemon.uid = Math.random();

   this.props.addToParty(pokemon);
};

Cela appelle alors une répartition qui déclenche le réducteur suivant. Ce qui vérifie essentiellement si l'objet n'a pas d'ID normal, puis remplacez le contenu par la charge utile envoyée. Il le fait mais met également à jour tous les objets précédents avec le même uid même si l'instruction if ne s'exécute pas contre eux.

const initState = {
 party: [
 { uid: 0 },
 { uid: 1 },
 { uid: 2 },
 { uid: 3 },
 { uid: 4 },
 { uid: 5 }
 ]
};


0 commentaires

3 Réponses :


3
votes

Le problème ici est que, lorsque vous cliquez pour sélectionner un pokémon, vous mutez les données que vous avez récupérées de l'API:

handleClick = pokemon => {
  this.props.addToParty({
    ...pokemon,
    uid: Math.random()
  });
};

Vous modifiez réellement l'état de réaction. Ce que vous devez faire est de cloner votre objet de données pokemon, d'ajouter un uid au clone que vous venez de générer et de mettre à jour votre état de redux avec celui-ci:

handleClick = pokemon => {
  pokemon.uid = Math.random(); // HERE
  this.props.addToParty(pokemon);
};

De cette façon, aucune référence au l'état de réaction réel est conservé. Parce que c'était ce qui se passait quand vous dites qu'il met à jour l'ancien squirtle avec le nouvel uid squirtles . Lorsque vous avez essayé d'ajouter un autre pokemon, vous avez mis à jour les données que vous avez récupérées de votre API qui ont également été référencées à partir de votre premier emplacement pokemon (à partir de votre état redux).


1 commentaires

Ah merci beaucoup, cela a du sens. Je suis encore nouveau pour réagir, alors j'ai vraiment besoin de me rappeler de ne jamais muter quoi que ce soit qui ait un rapport avec l'État.



1
votes

Dans react / redux, il est toujours préférable de ne pas muter les objets:

this.props.addToParty({...pokemon, uid: Math.random()});


0 commentaires

0
votes

Vous mutez l'état. Utilisez la syntaxe de propagation *** pour copier l'état avant la mise à jour.

return {
...state,
party: newArray
}


0 commentaires