Redux-persist 反应本机 AsyncStorage 对象序列化对象不相等

Redux-persist react native AsyncStorage Object Serialization Objects Not Equal

我正在使用 redux persist 按照文档中的描述在应用程序启动时自动保持和补充状态,特别是使用 AsyncStorage:https://github.com/rt2zz/redux-persist.

我在下面定义了一个 reducer,它将当前添加到购物车的产品保存在 state.products

case 'ADD_PRODUCT':
  let addedProducts = [...state.products]
  addedProducts.push(action.product);
  return {
    ...state,
    count: ++state.count,
    products: addedProducts
  };

case 'REMOVE_PRODUCT':
  let count = state.count;
  let removedProducts = [...state.products];
  let idxOfProduct = state.products.indexOf(action.product);
  if(idxOfProduct != -1){
    count = --state.count;
    removedProducts.splice(idxOfProduct,1);
  }

return{
    ...state,
    count: count,
    products: removedProducts
    }; 

#1。如果我发送 'ADD_PRODUCT',它会添加产品,然后如果我发送 'REMOVE_PRODUCT',它会按预期删除该项目。

#2.1 如果我发送 ADD_PRODUCT 然后重新加载我的应用程序,state.products 会按预期重新水化并包含最近添加的产品。

#2.1.However 在我重新加载应用程序后尝试调用 REMOVE_PRODUCT(与我在上面 #1 中调用 REMOVE_PRODUCT 的方式完全相同)。即使 state.products 包含产品 state.products.indexOf(action.product); returns 返回 -1,因此它不会被删除。

为什么在调用 REMOVE_PRODUCT 时,#1 中的 IndexOf 方法可以正常工作。但是,如果我添加一个产品(ADD_PRODUCT)然后重新加载我的应用程序并调用 REMOVE_PRODUCT,IndexOf returns -1 即使它存在于 state.products

发生这种情况是因为 indexOf 使用 strict reference equality 检查来查找数组中的元素。这意味着对象具有相同的字段和值是不够的:它需要是完全相同的对象。应用程序重新加载后,这永远不会是真的,因为原始对象已被销毁。

如果您的产品有某种唯一 ID 字段,最简单的方法是过滤列表以排除具有匹配 ID 的项目:

const products = state.products.filter(p => p.id !== action.product.id);
const count = products.length;

return { ...state, products, count };

我认为问题可能与 indexOf 处理对象相等性的方式有关。

无需重新加载,您正在添加和删除相同的对象引用,这没问题。

当您重新加载时,state.products 中加载的引用与 action.product 中的不同,因此 indexOf 无法找到它并且永远不会 returns 索引。

要解决此问题,我会使用产品 ID 在 state.products 数组中查找该产品,而不是尝试查找整个对象。

为了说明我的回答,这就是你正在做的事情:

var a = {obj: 0};
var b = [a];
b.indexOf({obj: 0}); // -1 not found

这是你应该做的:

var a = {id: '26833', obj: 0};
var b = [a];
b.findIndex(function(el){ //findIndex is not supported in IE, find a polyfill for it
   return el.id === '26833'
}); //0