Come faccio ad aggiungere un elemento all'array nel riduttore del redux nativo di React?


140

Come faccio ad aggiungere elementi nel mio array arr[]di stato redux nel riduttore? Lo sto facendo-

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
    }
}

Risposte:


363

Due diverse opzioni per aggiungere elementi a un array senza mutazione

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

O

case ADD_ITEM :
    return { 
        ...state,
        arr: state.arr.concat(action.newItem)
    }

1
Quale dovrebbe essere considerato preferibile?
Sapht

19
@sapht se stai scrivendo il codice in ES6 preferisci il primo che è IMO più leggibile ed elegante.
Yadhu Kiran,

5
Inoltre, il primo è puro, il secondo no. Dai documenti Redux: "È molto importante che il riduttore rimanga puro. Cose che non dovresti mai fare all'interno di un riduttore: 1. Muta i suoi argomenti; 2. Esegui effetti collaterali come chiamate API e transizioni di routing; 3. Chiama funzioni non pure, ad es. Date.now () o Math.random (). "
Robot affascinante

Ciao, @YadhuKiran puoi spiegarmi perché aggiungiamo un nuovo valore nel secondo indice dell'array e non sono riuscito a capirlo molto bene? arr: [...state.arr, why here?]
Oliver D

@OliverD, Quando si utilizza la sintassi spread come sopra, non si inserisce l'elemento nel secondo indice, ma nell'ultimo indice. Contrariamente a ciò, [action.newItem, ...state.arr]inserisce l'elemento nella prima posizione.
Yadhu Kiran,

22

pushnon restituisce l'array, ma la sua lunghezza ( documenti ), quindi quello che stai facendo è sostituire l'array con la sua lunghezza, perdendo l'unico riferimento ad esso che avevi. Prova questo:

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
     }
}

1
Qualcuno può rispondere a questa domanda con Object.assignper le modifiche dell'array all'interno dello stato, per favore?
Vennesa,

2
Perché avete bisogno Object.assign? È usato per gli oggetti ed è essenzialmente la stessa cosa. Dove hai arr:[...state.arr, action.newItem]puoi usare obj: Object.assign({}, state.obj, action.newItem, purché obje newItemsiano oggetti. Se vuoi farlo per l'intero stato, puoi semplicemente farloObject.assign({}, state, {arr: [..state.arr, action.newItem]})
martinarroyo

1
@martinarroyo, grazie anche io: var obj = { isLoading: true, data: ['a', 'b', 'c', 'd'] } var newObj = Object.assign({}, obj, { data: [...obj.data, 'e'] });e questo mi dà questo: { isLoading: true, data: [ 'a', 'b', 'c', 'd', 'e' ] }per newObj che è abbastanza buono per quello di cui ho bisogno. Ma volevo usare Object.assign senza l'operatore spread per produrre lo stesso risultato. È possibile?
Vennesa,

1
@Vennesa Suppongo che puoi sostituirlo con [].concat(obj.data, ['e']), se non vuoi usare le funzionalità ES6. Object.assign è pensato per gli oggetti e, sebbene non ti dia alcun errore nell'usarlo su un array, il risultato non è una concatenazione degli array. Se ci provi Object.assign({}, [1, 2, 3], [4]), ottieni [4, 2, 3]di conseguenza.
martinarroyo,

13

Se è necessario inserire una posizione specifica nell'array, è possibile effettuare ciò:

case ADD_ITEM :
    return { 
        ...state,
        arr: [
            ...state.arr.slice(0, action.pos),
            action.newItem,
            ...state.arr.slice(action.pos),
        ],
    }

Sono inciampato qui ... anche se questa risposta non corrisponde esattamente alla domanda sopra. Tuttavia, era esattamente quello che stavo cercando. Stavo cercando un modo per inserire un oggetto in un indice specifico in un array. Quindi, ho votato a favore della risposta. È stato molto utile e mi ha fatto risparmiare un po 'di tempo. Grazie!
Omostan,

0

Ho un campione

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;

1
aggiungi una descrizione
Spatel
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.