【问题标题】:How to change the state object when one of the fields is an array?当其中一个字段是数组时如何更改状态对象?
【发布时间】:2019-03-05 11:58:15
【问题描述】:

我有一个这种形式的状态树:

    const initialState = {
    total: 0,
    discount: 0,
    typeDiscount: 0,
    products: data
};

其中products字段是一个数组,数组是这样的:

[{
   "id":9090,
   "name":"Item1",
   "price":200,
   "discount":10,
   "type":"fiction",
   "quantity": 1,
   "img_url":"https://store.lexisnexis.com.au/__data/media/catalog/thumb//placeholder.jpg"
},
{
   "id":9091,
   "name":"Item2",
   "price":250,
   "discount":15,
   "type":"literature",
   "quantity": 1,
   "img_url":"https://store.lexisnexis.com.au/__data/media/catalog/thumb//placeholder.jpg"
}]

现在我正在尝试更改该数组中的数量,我是 Redux 的新手,所以请指导我如何做到这一点?

这是我的减速器:

case types.ADD_ITEM_CART:
        let product_add = state.products
        for (let i = 0; i < product_add.length; i++) {
            if (product_add[i].id === action.id) {
                product_add[i].quantity = product_add[i].quantity + 1
                break
            }
        }
        return dotProp.set(state, `products`, product_add);

【问题讨论】:

  • 你想改变哪个对象的数量?
  • 在initialState对象的product字段中我想改变数量。
  • 不要像这样改变你的状态,有更好的方法。所以,你有一个来自你的动作有效载荷的id,对吧?那你想把数量加一吗?
  • 是的,没错。我怎么做?我是新手,我总是对此感到困惑。
  • 你需要用 product_add 的新产品覆盖 state 中的产品所以 return {...state, product: product_add} 如果你想遵循 redux 的方式,你必须深入从状态复制(让 product_add = {...state.products } 为你的情况)而不是复制引用所以原始数据是不可变的,记住状态是不可变的所以只复制和覆盖

标签: javascript reactjs redux


【解决方案1】:

您可以使用Array.prototype.map 并迭代项目并更新与有效负载中的id 匹配的项目。

类似的东西:

const state = [{
    "id": 9090,
    "name": "Item1",
    "price": 200,
    "discount": 10,
    "type": "fiction",
    "quantity": 1,
    "img_url": "https://store.lexisnexis.com.au/__data/media/catalog/thumb//placeholder.jpg"
  },
  {
    "id": 9091,
    "name": "Item2",
    "price": 250,
    "discount": 15,
    "type": "literature",
    "quantity": 1,
    "img_url": "https://store.lexisnexis.com.au/__data/media/catalog/thumb//placeholder.jpg"
  }
];

const payload = {
  id: 9091
};

const nextState = state.map(product => {
  if (product.id !== payload.id) {
    // not our product, return as is
    return product;
  }
  return {
    ...product,
    quantity: product.quantity + 1
  }
});

console.log(nextState);
.as-console-wrapper {
  max-height: 100% !important;
}

要删除项目,您可以使用 Array.prototype.filter:

const state = [{
    "id": 9090,
    "name": "Item1",
    "price": 200,
    "discount": 10,
    "type": "fiction",
    "quantity": 1,
    "img_url": "https://store.lexisnexis.com.au/__data/media/catalog/thumb//placeholder.jpg"
  },
  {
    "id": 9091,
    "name": "Item2",
    "price": 250,
    "discount": 15,
    "type": "literature",
    "quantity": 1,
    "img_url": "https://store.lexisnexis.com.au/__data/media/catalog/thumb//placeholder.jpg"
  }
];

const payload = {
  id: 9091
};

const nextState = state.filter(product => product.id !== payload.id);

console.log(nextState);

【讨论】:

    【解决方案2】:

    使用扩展运算符...array.map(),您可以创建一个新的产品数组,其中所有不匹配 id 的产品将保持相同的对象引用,同时为您感兴趣的产品创建一个新的产品对象:

    case types.ADD_ITEM_CART:
        const updatedProducts = state.products.map(product => {
           if (product.id === action.id) {
                const newQuantity = product.quantity + 1;
                return { ...product, quantity: newQuantity };
            }
    
            return product;
        })
    
        return { ...state, products: updatedProducts };
    }
    

    编辑: 可以使用array.filter() 方法轻松实现删除,该方法将创建一个仅包含与您的谓词函数匹配的项目的新数组;在这种情况下,所有与您要删除的产品的 id 不匹配的产品:

     case types.REMOVE_ITEM_CART:
        const updatedProducts = state.products.filter(product => product.id !== action.id)
    
        return { ...state, products: updatedProducts };
    }
    

    【讨论】:

      【解决方案3】:

      不要像 Redux 或 React 本身那样改变你的状态。复制对象不会创建不同的对象。如果你改变了新的属性,你也改变了原来的属性。

      一般情况下,我们使用Object.assign 或扩展语法结合.map.filter 等方法。 Object.assign 或扩展语法也不会创建完全不同的对象。他们创建浅拷贝,这意味着一级拷贝。如果您更改新对象的嵌套属性,那么您将再次改变原始对象。所以,结合所有这些工具。

      case types.ADD_ITEM_CART: {
          // We are mapping our related array.
          const newProducts = state.products.map( el => {
            // If id does not match, return the element without doing nothing.
            if ( el.id !== action.id ) { return el };
            // id match, increment the quantity.
            return { ...el, quantity: el.quantity + 1 };
          })
          // Lastly, return our state again without mutating it.
          return { ...state, products: newProducts };
      }
      

      如果我们想从数组中删除一个项目,我们通常使用.filter 方法。

      const newProducts = state.products.filter( el => el.id !== action.id );
      return { ...state, products: newProducts };
      

      【讨论】:

        猜你喜欢
        • 2016-10-06
        • 1970-01-01
        • 2021-12-26
        • 1970-01-01
        • 1970-01-01
        • 2021-10-02
        • 2019-05-17
        • 2021-07-25
        • 1970-01-01
        相关资源
        最近更新 更多