Jak dodać element do tablicy w reduktorze React Native Redux?

140

Jak dodać elementy w mojej tablicy arr[]stanu Redux w reduktorze? Robię to-

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
źródło

Odpowiedzi:

363

Dwie różne opcje dodawania pozycji do tablicy bez mutacji

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

LUB

case ADD_ITEM :
    return { 
        ...state,
        arr: state.arr.concat(action.newItem)
    }
Yadhu Kiran
źródło
1
Który z nich należy uznać za lepszy?
sapht
19
@sapht, jeśli piszesz kod w ES6, preferuj pierwszy, który jest bardziej czytelny i elegancki IMO.
Yadhu Kiran
5
Ponadto pierwszy jest czysty, a drugi nie. Z dokumentacji Redux: „Bardzo ważne jest, aby reduktor pozostał czysty. Rzeczy, których nigdy nie powinieneś robić w reduktorze: 1. Mutuj jego argumenty; 2. Wykonuj efekty uboczne, takie jak wywołania API i przejścia routingu; 3. Wywołaj nieczyste funkcje, np. Date.now () lub Math.random () ”.
Charming Robot
Witaj @YadhuKiran, czy możesz mi wyjaśnić, dlaczego dodajemy nową wartość do drugiego indeksu tablicy, której nie rozumiem zbyt dobrze? arr: [...state.arr, why here?]
Oliver D
@OliverD, Kiedy składnia spreadu jest używana jak powyżej, element nie jest wstawiany na drugim indeksie, ale na ostatnim indeksie. W przeciwieństwie do tego, [action.newItem, ...state.arr]wstawiłby element na pierwszej pozycji.
Yadhu Kiran
22

pushnie zwraca tablicy, ale jej długość ( dokumenty ), więc to, co robisz, to zastępowanie tablicy jej długością, tracąc jedyne odniesienie do niej, jakie miałeś. Spróbuj tego:

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
źródło
1
Czy ktoś może odpowiedzieć na to pytanie Object.assignw sprawie zmian tablicy wewnątrz stanu?
Vennesa
2
Dlaczego potrzebujesz Object.assign? Jest używany do obiektów i zasadniczo jest tym samym. Gdzie masz arr:[...state.arr, action.newItem]można skorzystać obj: Object.assign({}, state.obj, action.newItempod warunkiem, że obji newItemsą obiektami. Jeśli chcesz to zrobić dla całego stanu, możesz to zrobićObject.assign({}, state, {arr: [..state.arr, action.newItem]})
martinarroyo
1
@martinarroyo, dzięki, tak zrobiłem: var obj = { isLoading: true, data: ['a', 'b', 'c', 'd'] } var newObj = Object.assign({}, obj, { data: [...obj.data, 'e'] });i daje mi to: { isLoading: true, data: [ 'a', 'b', 'c', 'd', 'e' ] }dla newObj, który jest wystarczająco dobry dla tego, czego potrzebuję. Ale chciałem użyć Object. assign bez operatora spreadu, aby uzyskać ten sam wynik. Czy to jest możliwe?
Vennesa
1
@Vennesa Myślę, że możesz go zastąpić [].concat(obj.data, ['e']), jeśli nie chcesz korzystać z funkcji ES6. Obiekt Object. assign jest przeznaczony dla obiektów i chociaż użycie go w tablicy nie spowoduje żadnych błędów, wynikiem nie jest konkatenacja tablic. Jeśli spróbujesz Object.assign({}, [1, 2, 3], [4]), otrzymasz [4, 2, 3]wynik.
martinarroyo
13

Jeśli chcesz wstawić w określone miejsce w tablicy, możesz to zrobić:

case ADD_ITEM :
    return { 
        ...state,
        arr: [
            ...state.arr.slice(0, action.pos),
            action.newItem,
            ...state.arr.slice(action.pos),
        ],
    }
JoeTidee
źródło
Natknąłem się tutaj ... chociaż ta odpowiedź nie pasuje do powyższego pytania. Niemniej jednak to było dokładnie to, czego szukałem. Szukałem sposobu na wstawienie obiektu do określonego indeksu w tablicy. Dlatego głosowałem za odpowiedzią. To było bardzo pomocne i pozwoliło mi zaoszczędzić trochę czasu. Dzięki!
Omostan
0

Mam próbkę

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
źródło
1
dodaj opis
SPatel