Je construis ma première application avec React et Redux. J'essaye de supprimer un élément d'un tableau dans mon réducteur en utilisant l'épissure.

Voici mon état:

  favourite: { recipes: [], wines: [], products: [] }

Voici mon action:

  if (action.type === "REMOVE_RECIPE_FROM_FAV") {
    let favourite = state.favourite;
    favourite.recipes.splice(action.data, 1);
    return {
      ...state,
      favourite: favourite,
    };
  }

Lorsque j'ai le favori console.log, je peux voir que je supprime l'élément, mais mon composant ne se met pas à jour.

Pourrais-tu m'aider s'il te plaît?

1
Davide 9 mai 2020 à 16:03

4 réponses

Meilleure réponse

Vous devez prendre soin de l'immuabilité de l'état redux. Vous devez faire une copie du tableau recipes, le modifier et le fusionner avec l'état sans affecter les autres.

if (action.type === "REMOVE_RECIPE_FROM_FAV") {
    let favourite = state.favourite;
    const cloneRecipes = [...favourite.recipes];
    cloneRecipes.splice(action.data, 1);

    return {
        ...state,
        favourite: {
            ...state.favourite,
            recipes: cloneRecipes
        }
    }
}

Notez que [...favourite.recipes] fait une copie superficielle du tableau recipes. Pour un tableau imbriqué, cela ne vous aide pas.

Je vous suggère d'utiliser plutôt la bibliothèque Immutability Helpers . En utilisant cette bibliothèque, la même tâche pourrait être effectuée comme:

if (action.type === "REMOVE_RECIPE_FROM_FAV") {
    return update(state, {
        favourite: {
            recipes: {$splice: [[action.data, 1]]}
        }
    });
}
1
Sajeeb Ahamed 9 mai 2020 à 13:20

Vous devez garder 2 règles à l'esprit lorsque vous utilisez des réducteurs

  1. Ne modifiez pas l'état d'origine

  2. Renvoyez toujours un nouvel objet d'état.

Vous ne pouvez pas renvoyer l'objet d'état d'origine car redux comparera l'objet d'état d'origine et l'objet d'état modifié renvoyé par le réducteur. Si ces deux objets ont la même adresse dans la mémoire, l'état modifié ne sera pas transmis à vos composants et par conséquent, ils ne seront pas rendus.

Dans votre cas, vous devez faire une copie de l'objet favourites et également faire une copie du tableau recipes. Ensuite, modifiez le tableau des recettes copiées et retournez l'objet copy of the favourite`

Notez qu'en copiant l'objet, je veux dire créer un nouvel objet en mémoire et copier les propriétés de l'objet qui est copié.

const { favourite } = state;

let favouriteCopy = { ...favourite, recipes: [...favourite.recipes]  };
favouriteCopy.recipes.splice(action.data, action.data + 1);

return favouriteCopy;
0
Yousaf 9 mai 2020 à 13:39

Comme Robin Zigmond a dit que vous devez renvoyer un nouvel état du réducteur et non le muter, utilisez plutôt array.filter pour supprimer le action.data du tableau favori.

    let favourite = state.favourite;
    // this return new items array removing action.data from it.
    let newFavouriteArray = favourite.filter(item => item !== action.data)
    return {
      ...state,
      favourite: newFavouriteArray,
    };
0
Ahmad Nawaz Khan 9 mai 2020 à 13:16

Vos réducteurs doivent être de pures fonctions, c'est-à-dire qu'ils ne doivent pas muter l'état transmis.

Cependant, ici, vous modifiez l'état, car la favourite variable que vous créez ne contient pas une copie de l'objet favori dans votre état, mais juste une référence à celui-ci . Par conséquent, lorsque vous utilisez splice, vous modifiez en fait le tableau d'origine recipes, pas en en créez un nouveau, donc Redux n'est pas capable de détecter qu'il a changé, puisqu'il s'agit en fait du même objet!

Pour éviter ce problème, vous pouvez faire quelque chose comme ceci:

if (action.type === "REMOVE_RECIPE_FROM_FAV") {
  return {
    ...state,
    favourite: {...favourite, 
                recipes: { state.favourite.recipes.slice(action.data, action.data + 1) }
    }
  };
}

Je suppose que action.data contient l'index de l'élément à supprimer.

0
Tao Gómez Gil 9 mai 2020 à 13:17