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

时间:2017-01-09 08:56:02

标签: javascript reactjs react-native redux react-redux

我正在使用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然后RELOAD我的应用程序,state.products会按预期重新水合并包含最近添加的产品。

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

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

2 个答案:

答案 0 :(得分:2)

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

如果没有重新加载,则添加和删除相同的对象引用,这没关系。

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

要解决此问题,我会使用产品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

答案 1 :(得分:1)

这种情况发生了,因为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 };