Як додати елемент до масиву у редукторі React нативної редукції?


140

Як додати елементи до мого масиву arr[]стану redux у редуктор? Я роблю це,

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

Відповіді:


363

Два різні варіанти для додавання елемента до масиву без мутації

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

АБО

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

1
Який слід вважати кращим?
sapht

19
@sapht, якщо ви пишете код в ES6, віддавайте перевагу першому, який є більш читаним та елегантним IMO.
Ядху Кіран

5
Також перший - чистий, другий - ні. З документів Redux: "Дуже важливо, щоб редуктор залишався чистим. Речі, які ви ніколи не повинні робити всередині редуктора: 1. Змінюйте свої аргументи; 2. Виконуйте такі побічні ефекти, як дзвінки API та маршрутизацію переходів; 3. Викликайте нечисті функції, наприклад Date.now () або Math.random (). "
Чарівний робот

Привіт, @YadhuKiran Ви можете мені пояснити, чому ми додаємо нове значення у другому індексі масиву, я не міг його дуже добре зрозуміти? arr: [...state.arr, why here?]
Олівер Д

@OliverD, Коли синтаксис розповсюдження використовується, як зазначено вище, він не вставляє елемент на другий індекс, а на останній індекс. На противагу цьому, [action.newItem, ...state.arr]елемент буде вставлений у першу позицію.
Ядху Кіран

22

pushне повертає масив, але довжину його ( документи ), тому те, що ви робите, це замінити масив на його довжину, втрачаючи єдине посилання на нього, яке ви мали. Спробуйте це:

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
Чи може хтось відповісти на це запитання Object.assignщодо зміни масиву всередині штату, будь ласка?
Веннеса

2
Навіщо вам це потрібно Object.assign? Він використовується для предметів, і це по суті те саме. Там, де у вас є, arr:[...state.arr, action.newItem]ви можете використовувати obj: Object.assign({}, state.obj, action.newItem, якщо це objі newItemє об’єкти. Якщо ви хочете зробити це для всієї держави, ви можете просто зробитиObject.assign({}, state, {arr: [..state.arr, action.newItem]})
martinarroyo

1
@martinarroyo, дякую, що я зробив: var obj = { isLoading: true, data: ['a', 'b', 'c', 'd'] } var newObj = Object.assign({}, obj, { data: [...obj.data, 'e'] });і це дає мені це: { isLoading: true, data: [ 'a', 'b', 'c', 'd', 'e' ] }для newObj, який достатньо хороший для того, що мені потрібно. Але я хотів використовувати Object.assign без оператора розповсюдження для отримання того ж результату. Це можливо?
Веннеса

1
@Vennesa Я думаю, що ви можете замінити його [].concat(obj.data, ['e']), якщо ви не хочете використовувати функції ES6. Object.assign призначений для об'єктів, і хоча він не дасть вам жодних помилок для використання його в масиві, результат не є з'єднанням масивів. Якщо ви спробуєте Object.assign({}, [1, 2, 3], [4]), ви отримаєте [4, 2, 3]результат.
martinarroyo

13

Якщо вам потрібно вставити певну позицію в масиві, ви можете зробити це:

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

Я спіткнувся тут ... хоча ця відповідь точно не відповідає питанню вище. Тим не менш, це було саме те, що я шукав. Я шукав спосіб вставити об’єкт у певний індекс у масиві. Отже, я проголосував відповідь. Це було дуже корисно і заощадило мені час. Дякую!
omostan

0

У мене є зразок

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
додати трохи опису
SPatel
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.