web-dev-qa-db-fra.com

empêche les objets en double d'être ajoutés à l'état réagissent redux

J'ai une question concernant la prévention de l'ajout de doublons dans mon magasin Redux.

Cela devrait être simple, mais pour une raison quelconque, rien ne fonctionne.

export const eventReducer = (state = [], action) => {

    switch(action.type) {

        case "ADD_EVENT":

            return [...state, action.event].filter(ev => {
                if(ev.event_id !== action.event.event_id){
                   return ev;
                }
            });


        default:
            return state;

    }

};

La action ressemble à quelque chose comme ci-dessous:

{
   type: "ADD_EVENT",
   event: { event_id: 1, name: "Chelsea v Arsenal" }
}

Le problème est que, parfois, l'API avec laquelle je travaille envoie des messages identiques via un WebSocket, ce qui signifie que deux événements identiques sont ajoutés à mon magasin.

J'ai adopté de nombreuses approches, mais je n'arrive pas à comprendre comment le faire fonctionner. J'ai essayé beaucoup de réponses SO, 

6
user7597670

Pourquoi votre code échoue?

Code:

return [...state, action.event].filter(ev => {
    if(ev.event_id !== action.event.event_id){
       return ev;
    }
});

Parce que vous ajoutez d’abord le nouvel élément, puis que vous filtrez le même élément , il n’ajoutera jamais la nouvelle valeur à l’état de réduction.


Solution:

Utilisez # array.findIndex pour vérifier si un élément existe déjà dans un tableau, sinon ajoutez seulement l’élément, sinon renvoyez le même état.

Écris-le comme ceci:

case "ADD_EVENT":

    let index = state.findIndex(el => el.event_id == action.event.event_id);

    if(index == -1)
        return [...state, action.event];
    return state;
3
Mayank Shukla

Solution: 

const eventReducer = ( state = [], action ) => {
    switch (action.type) {
        case 'ADD_EVENT':
            return state.some(( { event_id } ) => event_id === action.event.event_id)
                ? state
                : [...state, action.event];
        default:
            return state;
    }
};

Tester:

const state1 = eventReducer([], {
    type: 'ADD_EVENT',
    event: { event_id: 1, name: 'Chelsea v Arsenal' }
});

const state2 = eventReducer(state1, {
    type: 'ADD_EVENT',
    event: { event_id: 2, name: 'Chelsea v Manchester' }
});

const state3 = eventReducer(state2, {
    type: 'ADD_EVENT',
    event: { event_id: 1, name: 'Chelsea v Arsenal' }
});

console.log(state1, state2, state3);
1
Ivan Nikitovic

Vous pouvez utiliser Array.prototype.find () .

Exemple (non testé)

const eventExists = (events, event) => {
  return evets.find((e) => e.event_id === event.event_id);
}
export const eventReducer = (state = [], action) = > {
    switch (action.type) {
    case "ADD_EVENT":
      if (eventExists(state, action.event)) {
        return state;
      } else {
        return [...state, action.event];
      }
    default:
        return state;
    }
};

Mise à jour (commentaire de CodingIntrigue))

Vous pouvez également utiliser Array.prototype.some () pour une meilleure approche

const eventExists = (events, event) => {
  return evets.some((e) => e.event_id === event.event_id);
}
export const eventReducer = (state = [], action) = > {
    switch (action.type) {
    case "ADD_EVENT":
      if (eventExists(state, action.event)) {
        return state;
      } else {
        return [...state, action.event];
      }
    default:
        return state;
    }
};
1
bennygenel

Vous pouvez faire quelque chose comme ça, pour la partie logique, afin de vous assurer de ne pas avoir la même entrée deux fois.

const x = filter.arrayOfData(item => item.event_id !== EVENT_FROM_SOCKET);
if (x.length === 0) {
  // dispatch action here
} else {
  // ignore and do nothing
}
0
Adeel Imran

Vous devez faire attention lorsque vous utilisez des tableaux dans des réducteurs. Vous ajoutez essentiellement plus d'éléments à la liste lorsque vous appelez:

[...state, action.event]

Si vous utilisez plutôt une carte, vous pouvez éviter les doublons

const events = { ...state.events }
events[action.event.event_id] = action.event.name]
{...state, events }
0
Peter