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

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

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

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

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;

1
añadir alguna descripción
SPatel
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.