从嵌套的 redux 状态中删除元素

IT技术 reactjs redux immutability delete-file seamless-immutable
2021-04-06 21:57:55

我想从我的 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 文档,您更新嵌套对象的方式是:-

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 个键 , key1key2您不希望此操作更改shoppingCardReducer其中的以及您想要更改的键。

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

现在,请尝试以下操作:-

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

现在阅读state.shoppingReducers.products并开始循环遍历您的产品数组并从状态中替换该特定元素,保持其余部分不变。

然后返回新状态(您应该保持其余属性不变,否则您的应用程序可能会中断)

如果您发现这显然是一种糟糕的方法,而不是真正的 hack,reducers 与扩展运算符做同样的事情,但肯定是一种糟糕的方式。所以我会说尝试下一个选项。

第二种方式(immutablejs)

我建议你使用immutable.js使用起来非常简单和干净。

使用 immutable,您可以使用deleteIn函数从您的状态中删除您的特定产品元素。

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

PS:我还没有尝试过上面的代码,但稍加修改它应该可以工作。我希望你明白逻辑。

第三种方法(Normalizr)

您还可以尝试使您的 API 响应规范化,以使您的数据扁平化和访问权限。

但在以上三个中,我觉得 immutable 是最好的选择。

太好了,谢谢!从“无缝不可变”到“不可变”的唯一问题是我现在必须使用 .get() 函数来读取我的应用程序中的状态,这导致了很多问题。是否有任何技巧可以将状态作为普通的 js 对象而不是 Map 返回?
2021-05-28 21:57:55
是的......它不是一个黑客......你可以使用 map.toJS() 将地图转换回对象
2021-06-18 21:57:55

您可以简单地使用删除方法:

删除 this.props.register_reducer.selected_products['yourid'];

您必须实际注册一个 redux 函数并像这样使用它: this.props.isRegister(['selected_products.yoursku',null])
2021-06-13 21:57:55