1

Я хочу удалить элемент из моего состояния redux. Я использую бесшовные неизменяемые и его API для работы в состоянии. Но я не мог найти красивый способ удаления элемента, когда состояние вложенное.Удалить элемент из вложенного состояния редукции

Так элемент Я хочу удалить это: state.shoppingcartReducer.products[articleNr]

Спасибо!


import Immutable from 'seamless-immutable' 

import { addToShoppingcart, createShoppingCart } from '../actions/shoppingcartActions' 

const CREATE_SHOPPING_CART = 'CREATE_SHOPPING_CART' 
const ADD_PRODUCT = 'ADD_PRODUCT' 
const DELETE_PRODUCT = 'DELETE_PRODUCT' 
const UPDATE_QUANTITY = 'UPDATE_QUANTITY' 
const SUMMARY = 'SUMMARY' 

const initialState = Immutable({ 
    summary: { 
    sum: 0, 
    quantity: 0 
    } 
}) 

export default function shoppingcartReducer(state = initialState, action) { 
    switch (action.type) { 
    case ADD_PRODUCT: 
     return state 
     .setIn(['products', action.product.articleNr], addArticle(action)) 

    // case DELETE_PRODUCT: 
    // return ?? 

    case SUMMARY: 
     return state 
     .set('summary', calculateSums(action, state)) 

    case CREATE_SHOPPING_CART: 
     return state 
     .set(action.id, createCart(action)) 

    case UPDATE_QUANTITY: 
     return state. 
     set('summary', calculateQuantity(action, state)) 
    } 
    return state 
} 

function addArticle(action) { 
    return { 
    product: action.product 
    } 
} 

function calculateQuantity(action, state) { 
    return { 
    quantity: state.summary.quantity + action.quantity 
    } 
} 

function calculateSums(action, state) { 
    return { 
     sum: state.summary.sum + action.price, 
     quantity: state.summary.quantity + action.quantity 
    } 
} 

function calculateSumsDelete(action, state) { 
    return { 
     sum: state.summary.sum - action.product.price, 
     quantity: state.summary.quantity - action.product.quantity 
    } 
} 

function createCart(action) { 
    return { 
    id: action.id, 
    } 
} 

ответ

2

Я застрял в аналогичной ситуации некоторое время назад.

Итак, в соответствии с redux docs так, как вы обновить вложенный объект является: -

function updateVeryNestedField(state, action) { 
    return { 
     ....state, 
     first : { 
      ...state.first, 
      second : { 
       ...state.first.second, 
       [action.someId] : { 
        ...state.first.second[action.someId], 
        fourth : action.someValue 
       } 
      } 
     } 
    } 
} 

Но поскольку у вас есть массив в вашем состоянии это заставляет вас работать немного сложнее.

Итак, есть два способа, которыми вы можете это сделать.

Первый способ (Трудный путь)

Создать новый объект по своему усмотрению и обновить состояние и вернуть новое состояние. Теперь ключ здесь, чтобы создать новый объект состояния и не назначать текущее состояние новому объекту, иначе он будет мутирован.

Итак, создайте новый объект.

const newState ={} 

Теперь назначьте текущие значения состояния, которые вы не хотите менять в новое состояние. Скажите в вашем штате, что у вас есть 3 клавиши, key1, key2, которые вы не хотите, чтобы это действие изменилось и shoppingCardReducer, которое вы хотите изменить.

newState['key1']=//key1 value from current state 
newState['key2'] = //key2 value from current state 

Теперь попробуйте следующее: -

newState['shoppingCardReducer'] ={} 
newState['shoppingCardReducer']['products']={} 

Теперь прочитайте state.shoppingReducers.products и sttart цикл над массивом продуктов и заменить этот конкретный элемент из состояния, сохранить нетронутыми остальные.

Тогда вернуть новое состояние (Вы должны держать остальные свойства нетронутых еще ваше приложение может сломаться)

Если вы видите это явно плохой способ сделать это, на самом деле не хак, редукторы сделать то же самое с но, конечно, плохой способ. Поэтому я бы сказал, попробуйте следующий вариант.

Второй способ (immutablejs)

Я хотел бы предложить вам использовать immutable.js. Его очень легко и просто использовать.

С неизменяемым вы можете использовать функцию deleteIn, чтобы удалить конкретный элемент продукта из своего состояния.

data.deleteIn(["shoppingcartReducer",product,//your_to_deleted_element_index]) 

P.S: Я не использовал вышеуказанный код, но с небольшими изменениями он должен работать. Надеюсь, вы получите логику.

Третий способ (Normalizr)

Вы также можете попробовать сделать, чтобы normalize вашего ответа API, чтобы сделать данные плоскими и доступ к доступу.

Но среди выше трех я считаю неизменным лучший вариант.

+0

Thats awsome, спасибо! Единственное, что происходит от «бесшовного-неизменяемого» до «неизменяемого», это то, что теперь я должен использовать функцию .get() для чтения моего состояния в своем приложении, и это вызывает множество проблем. Есть ли какой-либо хак, чтобы вернуть состояние как обычный объект js вместо карты? – AlfredO

+0

yup ... его не взломать .. u может преобразовать карту обратно в объект, используя map.toJS() –

Смежные вопросы