2

I have here products that may have one or more than one images. Depending on the productCode. If the productCode is the they belong to the same product. productCode could be found on the filename of the images, its after the first underscore. For instance if the filename is AA_BB_CC.jpg. The productCode is BB.

You can check samples images in my codesandbox.

So if images have the same productCode, it should add up to the product. My problem is on this part. Adding images of product with the same productCode.

Here's the codesandbox CLICK HERE

CODE

  return {
    ...state,
    products: [...state.products, ...action.payload]
  };

EXPECTED OUTPUTenter image description here

Response of expected output

enter image description here

4
  • I don't think you necessarily need to jump to using Immer to accomplish what you want, Redux describes the immutable update pattern quite well. It's difficult to understand what the crux of your question is. Are you asking how to figure out if an added image is already contained in the productImages array of a specific product by code? Are you asking how to handle the state update? You seem to be missing an attempt at doing this in your codesandbox. Commented Nov 10, 2021 at 17:35
  • BTW, if you do want to use Immer then I highly suggest just upgrading to Redux-Toolkit which uses Immer under the hood of its reducer functions and makes writing your state slices, actions, and reducers drastically less boilerplatey. Commented Nov 10, 2021 at 17:36
  • @DrewReese. For now,I dont want to use immer. Can you help me with this? Thank you. Commented Nov 10, 2021 at 17:52
  • Sure. I linked the immutable update pattern for how to handle actually updating state. To handle figuring out the code match, if the image filenames are consistent then you could probably string split the image filename on _ and take the second element from the returned array to match a product code. Once you know which product the image belongs to it's a matter of shallow copying these chunks of state to append the image object into the images array. Commented Nov 10, 2021 at 18:02

2 Answers 2

2

I see you already do the string splitting in the file uploader when you create the file image objects. In this case you just need to check the generated productCode of the image object payloads to see if it is already contained in the products array. If it isn't then generate the new "product" state object and add the image to the array, otherwise apply the immutable update pattern to shallow copy state and append the new file object.

Since each product in the action payload could potentially belong to different products you'll need to iterate this array in order to determine where each new product should be merged.

case appConstants.UPLOAD_PRODUCT_SUCCESS:
  // (1) iterate the product images array
  return action.payload.reduce(
    (
      state,
      {
        productCode,
        productName,
        productCategory,
        imageFile,
        imageFileName
      }
    ) => {
      // (2) Check if the product is already in state
      const shouldUpdate = state.products.some(
        (product) => product.productCode === productCode
      );

      // (3a) If we just need to return updated state with added new image
      if (shouldUpdate) {
        return {
          ...state,
          // (4) shallow copy the products array
          products: state.products.map((product) =>
            product.productCode === productCode
              // (4b) If this is the matching product, shallow copy product
              // append a new image file object with new id
              ? {
                  ...product,
                  productImages: product.productImages.concat({
                    id: uuidV4(),
                    imageFile,
                    imageFileName
                  })
                }
              // (4b) copy forward existing product object
              : product
          )
        };
      }

      // (3b) Create a new product object and initially populate images array
      return {
        ...state,
        products: state.products.concat({
          productCode,
          productName,
          productCategory,
          productExisting: true,
          productImages: [
            {
              id: uuidV4(),
              imageFile,
              imageFileName
            }
          ]
        })
      };
    },
    state
  );

Edit redux-added-array-of-object-inside-another-aray-in-react

enter image description here

Sign up to request clarification or add additional context in comments.

Comments

0

You can do this with immer

the reducer can use the produce function from immer to push new images to the correct "proudctImages" array according to the "productCode"

import produce from 'immer';

...
return {
  ...state,
  products: produce(state.products, draftProducts => {
    const product = findProductWithProductCode(draftProducts, action.payload.productCode);
    product.productImages.push(...action.payload.productImages)
  })
};

You also need the productCode information for the new images.

"findProductWithProductCode" just loop through draftProducts and find the array element which "productCode" = action.payload.productCode

2 Comments

How cam I do this without using immer?
I see @Drew Reese post a good answer about this. you need to create a new copy for all of the object you want to update (include contain it). I still recommend you to use immer if there is no other consideration. it's more simple and readable. it also mentioned on the redux page

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.