Как добавить элемент в массив в редукторе React native redux?


148

Как мне добавить элементы в свой массив arr[]состояния редукции в редукторе? Я делаю это-

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

Ответы:


379

Два разных варианта добавления элемента в массив без изменения

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]вставит элемент в первую позицию.
Ядху Киран

23

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просьбой об изменении массива внутри состояния?
Vennesa

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 без оператора распространения, чтобы получить тот же результат. Это возможно?
Vennesa

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

14

Если вам нужно вставить в определенную позицию в массиве, вы можете сделать это:

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

1
Я споткнулся здесь ... хотя этот ответ не совсем соответствует поставленному выше вопросу. Тем не менее, это было именно то, что я искал. Я искал способ вставить объект в определенный индекс в массиве. Следовательно, я проголосовал за ответ. Это было очень полезно и сэкономило мне время. Благодарность!
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.