Comment ajouter un élément au tableau dans le réducteur du redux natif React?

140

Comment ajouter des éléments dans mon tableau arr[]d'état redux dans Reducer? Je fais ça

import {ADD_ITEM} from '../Actions/UserActions'
const initialUserState = {
    arr:[]
}

export default function userState(state = initialUserState, action)
{
    console.log(arr);
    switch (action.type)
    {
        case ADD_ITEM: 
            return { 
                      ...state,
                      arr: state.arr.push([action.newItem])
                   }

        default:
            return state
    }
}
coderzzz18
la source

Réponses:

363

Deux options différentes pour ajouter un élément à un tableau sans mutation

case ADD_ITEM :
    return { 
        ...state,
        arr: [...state.arr, action.newItem]
    }

OU

case ADD_ITEM :
    return { 
        ...state,
        arr: state.arr.concat(action.newItem)
    }
Yadhu Kiran
la source
1
Lequel devrait être considéré comme préférable?
sapht
19
@sapht si vous écrivez du code dans ES6, préférez le premier qui est plus lisible et élégant IMO.
Yadhu Kiran
5
De plus, le premier est pur, le second ne l'est pas. Extrait de la documentation Redux: "Il est très important que le réducteur reste pur. Ce que vous ne devriez jamais faire à l'intérieur d'un réducteur: 1. Muter ses arguments; 2. Effectuer des effets secondaires comme des appels d'API et des transitions de routage; 3. Appeler des fonctions non pures, par exemple Date.now () ou Math.random (). "
Charming Robot
Bonjour, @YadhuKiran pouvez-vous m'expliquer pourquoi nous ajoutons une nouvelle valeur dans le deuxième index du tableau, je ne pouvais pas très bien le comprendre? arr: [...state.arr, why here?]
Oliver D le
@OliverD, Lorsque la syntaxe de propagation est utilisée comme ci-dessus, elle n'insère pas d'élément au deuxième index, mais au dernier index. Contrairement à cela, [action.newItem, ...state.arr]insérer l'élément à la première position.
Yadhu Kiran le
22

pushne renvoie pas le tableau, mais la longueur de celui-ci ( docs ), donc ce que vous faites est de remplacer le tableau par sa longueur, en perdant la seule référence que vous aviez. Essaye ça:

import {ADD_ITEM} from '../Actions/UserActions'
const initialUserState = {

    arr:[]
}

export default function userState(state = initialUserState, action){
     console.log(arr);
     switch (action.type){
        case ADD_ITEM :
          return { 
             ...state,
             arr:[...state.arr, action.newItem]
        }

        default:return state
     }
}
martinarroyo
la source
1
Quelqu'un peut-il répondre à cette question avec Object.assignpour les changements du tableau à l'intérieur de l'état s'il vous plaît?
Vennesa
2
Pourquoi avez-vous besoin Object.assign? Il est utilisé pour les objets, et c'est essentiellement la même chose. Là où vous avez, arr:[...state.arr, action.newItem]vous pouvez utiliser obj: Object.assign({}, state.obj, action.newItem, à condition que objet newItemsoient des objets. Si vous voulez faire cela à l'ensemble de l'État, vous pouvez simplement le faireObject.assign({}, state, {arr: [..state.arr, action.newItem]})
martinarroyo
1
@martinarroyo, merci donc je l'ai fait: var obj = { isLoading: true, data: ['a', 'b', 'c', 'd'] } var newObj = Object.assign({}, obj, { data: [...obj.data, 'e'] });et ça me donne ceci: { isLoading: true, data: [ 'a', 'b', 'c', 'd', 'e' ] }pour newObj qui est assez bon pour ce dont j'ai besoin. Mais je voulais utiliser Object.assign sans l'opérateur de propagation pour produire le même résultat. Est-ce possible?
Vennesa
1
@Vennesa Je suppose que vous pouvez le remplacer par [].concat(obj.data, ['e']), si vous ne voulez pas utiliser les fonctionnalités ES6. Object.assign est destiné aux objets, et bien qu'il ne vous donne aucune erreur de l'utiliser sur un tableau, le résultat n'est pas une concaténation des tableaux. Si vous essayez Object.assign({}, [1, 2, 3], [4]), vous obtenez [4, 2, 3]en conséquence.
martinarroyo
13

Si vous devez insérer dans une position spécifique dans le tableau, vous pouvez le faire:

case ADD_ITEM :
    return { 
        ...state,
        arr: [
            ...state.arr.slice(0, action.pos),
            action.newItem,
            ...state.arr.slice(action.pos),
        ],
    }
JoeTidee
la source
Je suis tombé ici ... même si cette réponse ne correspond pas exactement à la question ci-dessus. Néanmoins, c'était exactement ce que je recherchais. Je cherchais un moyen d'insérer un objet dans un index spécifique dans un tableau. Par conséquent, j'ai voté la réponse. Cela a été très utile et m'a fait gagner du temps. Merci!
omostan
0

J'ai un échantillon

import * as types from '../../helpers/ActionTypes';

var initialState = {
  changedValues: {}
};
const quickEdit = (state = initialState, action) => {

  switch (action.type) {

    case types.PRODUCT_QUICKEDIT:
      {
        const item = action.item;
        const changedValues = {
          ...state.changedValues,
          [item.id]: item,
        };

        return {
          ...state,
          loading: true,
          changedValues: changedValues,
        };
      }
    default:
      {
        return state;
      }
  }
};

export default quickEdit;
Long Nguyen Qui
la source
1
ajouter une description
SPatel