Como adiciono um elemento à matriz no redutor do React nativo redux?

140

Como adiciono elementos na minha matriz arr[]de estado redux no redutor? Eu estou fazendo isso-

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
fonte

Respostas:

363

Duas opções diferentes para adicionar item a uma matriz sem mutação

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

OU

case ADD_ITEM :
    return { 
        ...state,
        arr: state.arr.concat(action.newItem)
    }
Yadhu Kiran
fonte
1
Qual deles deve ser considerado preferível?
sapht
19
@ sapht Se você estiver escrevendo código no ES6, prefira o primeiro, que é o IMO mais legível e elegante.
Yadhu Kiran
5
Além disso, o primeiro é puro, o segundo não. Nos documentos do Redux: "É muito importante que o redutor permaneça puro. Coisas que você nunca deve fazer dentro de um redutor: 1. Mude seus argumentos; 2. Realize efeitos colaterais como chamadas de API e transições de roteamento; 3. Chame funções não puras, por exemplo, Date.now () ou Math.random (). "
Charming Robot
Olá, @YadhuKiran você pode me explicar por que adicionamos novo valor no segundo índice da matriz que eu não conseguia entender muito bem? arr: [...state.arr, why here?]
Oliver D
@OliverD, Quando a sintaxe de propagação é usada como acima, ela não está inserindo elemento no segundo índice, mas no último índice. Em contraste com isso, [action.newItem, ...state.arr]inseriria o elemento na primeira posição.
Yadhu Kiran em 29/01
22

pushnão retorna a matriz, mas o comprimento ( docs ); portanto, o que você está fazendo é substituir a matriz pelo comprimento, perdendo a única referência a ela. Tente o seguinte:

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
fonte
1
Alguém pode responder a esta pergunta com Object.assignas alterações da matriz dentro do estado, por favor?
Vennesa
2
Por que você precisa Object.assign? É usado para objetos e é essencialmente a mesma coisa. Onde você arr:[...state.arr, action.newItem]pode usar obj: Object.assign({}, state.obj, action.newItem, desde que obje newItemsejam objetos. Se você quiser fazer isso para todo o estado, você pode simplesmente fazerObject.assign({}, state, {arr: [..state.arr, action.newItem]})
martinarroyo
1
@martinarroyo, obrigado por isso: var obj = { isLoading: true, data: ['a', 'b', 'c', 'd'] } var newObj = Object.assign({}, obj, { data: [...obj.data, 'e'] });e isso me dá o seguinte: { isLoading: true, data: [ 'a', 'b', 'c', 'd', 'e' ] }para newObj, que é bom o suficiente para o que eu preciso. Mas eu queria usar Object.assign sem o operador spread para produzir o mesmo resultado. Isso é possível?
Vennesa
1
@Vennesa Eu acho que você pode substituí-lo por [].concat(obj.data, ['e']), se você não quiser usar os recursos do ES6. Object.assign é destinado a objetos e, embora não dê erros para usá-lo em uma matriz, o resultado não é uma concatenação das matrizes. Se você tentar Object.assign({}, [1, 2, 3], [4]), você obtém [4, 2, 3]como resultado.
martinarroyo
13

Se você precisar inserir em uma posição específica na matriz, faça o seguinte:

case ADD_ITEM :
    return { 
        ...state,
        arr: [
            ...state.arr.slice(0, action.pos),
            action.newItem,
            ...state.arr.slice(action.pos),
        ],
    }
JoeTidee
fonte
Eu tropecei aqui ... embora essa resposta não se encaixe exatamente na pergunta acima. No entanto, era exatamente o que eu estava procurando. Eu estava procurando uma maneira de inserir um objeto em um índice específico em uma matriz. Por isso, votei a resposta. Foi muito útil e me salvou algum tempo. Obrigado!
omostan 6/06
0

Eu tenho uma amostra

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
fonte
1
adicione alguma descrição
SPatel