我怎样才能改变我的状态而不必通过 API 重新加载整个 json 对象

How can I mutate my state without having to reload the entire json object via the API

我将 reactjs 与 redux 结合使用,并且在 UI 上显示类别以及与其关联的产品。

当用户将产品移至另一个类别时,我不想像现在这样重新加载整个 JSON 文件,因为 JSON 实际上非常大。

如何通过从一个类别的 catProducts 集合中删除 productId 并将 productId 添加到另一个类别的 catProducts 集合来改变这个 JSON 文件。

{
  "shop" : {

    "categories": [
      {
        id: 1,
        name: "category1",
        "catProducts" : [
          {
            productId: 123
          }          
        ]
      },
      {
        id: 2,
        name: "category2",
        "catProducts" : [
          {
            productId: 456
          }          
        ]
      },
      {
        id: 3,
        name: "category3",
        "catProducts" : [
          {
            productId: 789
          }          
        ]
      }
    ]

  }

}

下面是我的操作和减速器,如您所见,每次移动产品时我都会重新加载整个类别的产品。 我需要做的就是在调用 API 之后,通过从一个 catProducts 中删除 productId 并将其添加到另一个来改变我的状态。 我该怎么做?

操作:

moveProduct: (data) => {
  return dispatch => {
  var url = '....'; // api to move the product in db
  axios.post(url, reqArgs)
    .then(function(resp) {
      dispatch(Actions.fetchCategoriesAndProducts(data.shopId));
    });
  };
},

减速器:

case Constants.FETCH_CATEGORIES_AND_PRODUCTS:
  return {...state, fetching: false, shop: action.data };

鉴于您有一个索引 fromIndex 代表要将产品移动到的 categories 数组索引,toIndex 代表要将产品移动到的 categories 数组索引, 和要移动的产品的 productId,你可以这样做:

const data = {
  shop: {
    categories: [
      {
        id: 1,
        name: "category1",
        catProducts: [
          {
            productId: 123
          }
        ]
      },
      {
        id: 2,
        name: "category2",
        catProducts: [
          {
            productId: 456
          }
        ]
      },
      {
        id: 3,
        name: "category3",
        catProducts: [
          {
            productId: 789
          }
        ]
      }
    ]
  }
};

const fromCategoryIndex = 0;
const toCategoryIndex = 1;
const productId = 123;

const categories = [...data.shop.categories];

categories[fromCategoryIndex] = {
  ...categories[fromCategoryIndex],
  catProducts: categories[fromCategoryIndex].catProducts.filter(
    product => product.productId !== productId
  )
};

categories[toCategoryIndex] = {
  ...categories[toCategoryIndex],
  catProducts: [...categories[toCategoryIndex].catProducts, { productId }]
};

console.log(categories);