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

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

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

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),
        ],
    }

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;

1
dodaj opis
SPatel
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.