Home > OS >  Delete Item inside an Array of an Array in React and Redux
Delete Item inside an Array of an Array in React and Redux

Time:11-26

I have an item inside an array of an array and I want to target it and delete it. My problem is how do I access it and delete that particular item without mutating it.

Codesandbox is here

CLICK HERE

case appConstants.DELETE_IMAGE_SUCCESS:
  return {
    ...state,
    products: state.productImages.filter((item) => item !== action.payload)
  };

CodePudding user response:

You should pass an additional payload - product. So that we can find the target product in state.products array by productCode. Suppose ProductCode can Identity a product.

Only use imageFileName is unable to determine which product it belongs to.

case appConstants.DELETE_IMAGE_SUCCESS:
      console.log(state);
      const nState = {
        ...state,
        products: state.products.map((item) => {
          if (item.productCode !== action.payload.product.productCode)
            return item;
          return {
            ...item,
            productImages: item.productImages.filter(
              (v) => v.imageFileName !== action.payload.imageFileName
            )
          };
        })
      };
      console.log(nState);
      return nState;

App.js:

// ...
const onDeleteImage = (imageFileName, product) => {
    dispatch(deleteImage({ imageFileName, product }));
  };

  return (
    <div className="App">
      {(products || []).map((product, index) => (
        <ProductCard
          product={product}
          key={index}
          onDeleteImage={(imageFileName) =>
            onDeleteImage(imageFileName, product)
          }
        />
      ))}
    </div>
  );
// ...

CodeSandbox

CodePudding user response:

Here's the conceptual solution:

case appConstants.DELETE_IMAGE_SUCCESS:
  return {
    ...state,
    products: state.products.map(product => ({
      ...product,
      productImages: (product.productImages ?? [])
        .filter(({imageFileName}) => imageFileName !== action.payload),
    })),
  };

Caveat: if more than one product has an image with the same file name as the one you are deleting, it will be deleted from the other products as well. (This is currently a limitation of the information provided in your payload.) If that description is a bug for your program, then you'll need to also provide a product ID in the payload so that you only filter images for the matching product.

CodePudding user response:

You need to pass productIndex or id along with the imageFileName to correctly do the delete. Otherwise, all the products having the same imageFileName will be deleted.

Try this

 case appConstants.DELETE_IMAGE_SUCCESS:
      return {
        ...state,
        products: (state.products || []).map((item, itemIndex) => {
          if (itemIndex === action.payload.productIndex) {
            return {
              ...item,
              productImages: item.productImages.filter(
                (image) => image.imageFileName !== action.payload.imageFileName
              )
            };
          }
          return item;
        })
      };

In App.js file

  const onDeleteImage = (productIndex, imageFileName) => {
    dispatch(deleteImage(productIndex, imageFileName));
  };

in actions index.js file

export const deleteImage = (productIndex, imageFileName) => {
  return {
    type: appConstants.DELETE_IMAGE_SUCCESS,
    payload: {
      productIndex,
      imageFileName
    }
  };
};

In MediaCard.js file

 <Button
          type="button"
          color="primary"
          variant="contained"
          onClick={() => onDeleteImage(productIndex, data.imageFileName)}
        >

Code sandbox => https://codesandbox.io/s/redux-added-array-of-object-inside-another-aray-in-react-forked-xmghr?file=/src/reducers/productReducer.js

  • Related