¿Cómo agrego un elemento a la matriz en el reductor de React Native Redux?

140

¿Cómo agrego elementos en mi matriz arr[]de estado redux en reductor? Yo estoy haciendo esto-

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
fuente

Respuestas:

363

Dos opciones diferentes para agregar elementos a una matriz sin mutación

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

O

case ADD_ITEM :
    return { 
        ...state,
        arr: state.arr.concat(action.newItem)
    }
Yadhu Kiran
fuente
1
¿Cuál debe considerarse preferible?
Sapht
19
@sapht si está escribiendo código en ES6, prefiera el primero, que es más legible y elegante.
Yadhu Kiran
55
Además, el primero es puro, el segundo no lo es. De los documentos de Redux: "Es muy importante que el reductor se mantenga puro. Cosas que nunca debes hacer dentro de un reductor: 1. Mutar sus argumentos; 2. Realizar efectos secundarios como llamadas API y transiciones de enrutamiento; 3. Llamar a funciones no puras, por ejemplo, Date.now () o Math.random () ".
Robot encantador
Hola, @YadhuKiran, ¿puedes explicarme por qué agregamos un nuevo valor en el segundo índice de la matriz? ¿No podría entenderlo muy bien? arr: [...state.arr, why here?]
Oliver D
@OliverD, cuando la sintaxis extendida se usa como se indicó anteriormente, no está insertando un elemento en el segundo índice, sino en el último índice. En contraste con esto, [action.newItem, ...state.arr]insertaría el elemento en la primera posición.
Yadhu Kiran
22

pushno devuelve la matriz, sino su longitud ( docs ), por lo que lo que está haciendo es reemplazar la matriz con su longitud, perdiendo la única referencia que tenía. Prueba esto:

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
fuente
1
¿Alguien puede responder esta pregunta con Object.assignlos cambios de la matriz dentro del estado por favor?
Vennesa
2
¿Por qué lo necesitas Object.assign? Se usa para objetos, y es esencialmente lo mismo. Donde se tiene arr:[...state.arr, action.newItem]se puede utilizar obj: Object.assign({}, state.obj, action.newItem, siempre que objy newItemson objetos. Si quieres hacer eso a todo el estado, puedes hacerloObject.assign({}, state, {arr: [..state.arr, action.newItem]})
martinarroyo
1
@martinarroyo, gracias, así que lo hice: var obj = { isLoading: true, data: ['a', 'b', 'c', 'd'] } var newObj = Object.assign({}, obj, { data: [...obj.data, 'e'] });y me da esto: { isLoading: true, data: [ 'a', 'b', 'c', 'd', 'e' ] }para newObj, que es lo suficientemente bueno para lo que necesito. Pero quería usar Object.assign sin el operador de propagación para producir el mismo resultado. ¿Es eso posible?
Vennesa
1
@Vennesa Supongo que puede reemplazarlo [].concat(obj.data, ['e'])si no desea utilizar las funciones de ES6. Object.assign está destinado a objetos, y aunque no le dará ningún error al usarlo en una matriz, el resultado no es una concatenación de las matrices. Si lo intentas Object.assign({}, [1, 2, 3], [4]), obtienes [4, 2, 3]como resultado.
martinarroyo
13

Si necesita insertar en una posición específica en la matriz, puede hacer esto:

case ADD_ITEM :
    return { 
        ...state,
        arr: [
            ...state.arr.slice(0, action.pos),
            action.newItem,
            ...state.arr.slice(action.pos),
        ],
    }
JoeTidee
fuente
Tropecé aquí ... aunque esta respuesta no se ajusta exactamente a la pregunta anterior. Sin embargo, era exactamente lo que estaba buscando. Estaba buscando una manera de insertar un objeto en un índice específico en una matriz. Por lo tanto, voté la respuesta. Fue muy útil y me ahorró algo de tiempo. ¡Gracias!
omostan
0

Tengo una muestra

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
fuente
1
añadir alguna descripción
SPatel