Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
829 views
in Technique[技术] by (71.8m points)

reactjs - Remove element from nested redux state

I want to remove a element from my redux state. Im using seamless-immutable and its API to operate on the state. But I couldn't find any nice looking way to delete a element when the state is nested.

So the element I want to delete is: state.shoppingcartReducer.products[articleNr]

Thanks!


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,
  }
}
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

I was stuck in a similar situation sometime back.

So according the redux docs the way you update nested object is :-

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

But since you have array in your state it makes you work bit more difficult.

So there are 2 ways in which you can do this.

First way(The hard way)

Create a new object on your own and update the state and return the new state. Now the key here to create a new state object and not assign your current state to the the new object else it would be mutated.

So, create a new object .

const newState ={}

Now assign you current state values which you dont want to change to the new state. Say in your state you have 3 keys , key1, key2 which you dont want this action to change and shoppingCardReducer which you want to change.

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

Now, try following:-

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

Now read state.shoppingReducers.products and sttart looping over your products array and replace that particular element from the state, keep rest intact.

Then return the new state(You should keep rest of properties intact else your app can break)

If you see this is clearly a bad way to do it, not really a hack, reducers do same thing with spread operator but surely a bad way.So I would say try out next option.

Second way(immutablejs)

I would suggest you to use immutable.js. Its really easy and clean to use .

With immutable you can use deleteIn function to remove your particular particular product element from your state.

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

P.S: I havent tried the above code but with little modification it should work. I hope you get the logic.

Third Method(Normalizr)

You can also try make to normalize your API response to make your data flat and access to access.

But among above three I feel immutable is the best option.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...