简体   繁体   中英

React update array state in Redux

I am quite new with React and Redux. I manage to update existing item within an array with the following

case ACTION_TYPES.SET_PREPARATION_ITEM:
      const { id, x, y, rotation } = action.payload;
      const currentPreparationItem = state.entity.preparationItems[id];
      currentPreparationItem.x = x;
      currentPreparationItem.y = y;
      currentPreparationItem.rotation = rotation;
      return { ...state, preparationItems: { ...state.entity.preparationItems } };

Now I am trying to add new item into the array with the following code

case ACTION_TYPES.ADD_PREPARATION_ITEM:
      const implant: IProductMySuffix = action.payload;
      const preparationItem: IPreparationItemMySuffix = {};
      preparationItem.x = 10;
      preparationItem.y = 10;
      preparationItem.productId = implant.id;
      preparationItem.image = implant.image;
      preparationItem.imageContentType = implant.imageContentType;
      const result = { ...state, preparationItems: { ...state.entity.preparationItems.concat(preparationItem) } } 
      return result;

If I debug correctly, result const will have an array with one item. However the in the render method it does not seem to detect if the array has any elements. Any idea what might cause this ?

Added portion of my components

const mapStateToProps = (storeState: IRootState) => ({
  users: storeState.userManagement.users,
  customers: storeState.customer.entities,
  businesses: storeState.business.entities,
  products: storeState.product.entities,
  preparationEntity: storeState.preparation.entity,
  loading: storeState.preparation.loading,
  updating: storeState.preparation.updating,
  updateSuccess: storeState.preparation.updateSuccess
});

const mapDispatchToProps = {
  getUsers,
  getCustomers,
  getBusinesses,
  getEntity,
  getProducts,
  updateEntity,
  setBlob,
  createEntity,
  reset,
  setPreparationItem,
  addPreparationItem
};

First of all, you're mutating the state, which is against redux's rules

case ACTION_TYPES.SET_PREPARATION_ITEM:
      const { id, x, y, rotation } = action.payload;
      const currentPreparationItem = {...state.entity.preparationItems[id]}; // create a new object instance
      currentPreparationItem.x = x;
      currentPreparationItem.y = y;
      currentPreparationItem.rotation = rotation;
      const entity = state.entity ? {...state.entity} : {};
      const preparationItems = entity.preparationItems ? [...entity.preparationItems] : [] // Create a new Array instance
      preparationItems[id] = currentPreparationItem;
      entity.preparationItems = preparationItems;
      return {
        ...state,
        entity
      };

Second: you're spreading preparationItems as an object, but it's actually an array (based on your question description)

case ACTION_TYPES.ADD_PREPARATION_ITEM:
      const implant: IProductMySuffix = action.payload;
      const preparationItem: IPreparationItemMySuffix = {};
      preparationItem.x = 10;
      preparationItem.y = 10;
      preparationItem.productId = implant.id;
      preparationItem.image = implant.image;
      preparationItem.imageContentType = implant.imageContentType;
      const entity = state.entity ? {...state.entity} : {};
      // Create a new Array instance and add the new object at the end
      entity.preparationItems = entity.preparationItems ? [
        ...entity.preparationItems,
        preparationItem
      ] : [preparationItem];
      const result = {
        ...state,
        entity
      } 
      return result;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM