How to prevent component from rerendering on every order change using react-sortable-hoc?

342 views Asked by At

I'm using react-sortable-hoc to display image gallery, and to be able to reorder images by dragging and dropping. However, I have some weird behaviour of my components. Whenever I sort images, they disappear from the screen for a second, and rerender again. This happens even when I'm not changing the order of images. What could I be doing wrong?

Here is my code:

import React, {
   Dispatch, SetStateAction, useEffect, useState,
} from 'react';
import { SortableContainer, SortableElement, SortableHandle } from 'react-sortable-hoc';
import { ProductImageType } from '../../../../modules/products/types/ProductImageType';
import SingleProductImage from './SingleProductImage';

interface Props {
images: ProductImageType[]
cropProductImage: (imageId: number, width: number, height: number, x: number, y: number) => 
void
showCropModal: boolean,
loading: boolean,
setShowCropModal: Dispatch<SetStateAction<boolean>>
deleteHandler: (imageId: number) => void
}

const ProductGallery: React.FC<Props> = ({
  images, loading, deleteHandler,
}) => {
  const [orderedImages, setOrderedImages] = useState<ProductImageType[]>(images);
  const [imagetoCrop, setImagetoCrop] = useState<ProductImageType>();

  const SortableGallery: any = SortableContainer(({ children }: {children: any}) => <div 
  className="row mx-auto mb-10">{children}</div>);

  const SortableImage: any = SortableElement(({
    image, setShowCropModal, setImagetoCrop, deleteHandler, isMainImage,
  }: {image: ProductImageType,
    setShowCropModal:Dispatch<SetStateAction<boolean>>,
    setImagetoCrop: Dispatch<SetStateAction<ProductImageType | undefined>>,
    deleteHandler: (imageId: number) => void,
    isMainImage: boolean, }) => (
      <SingleProductImage
        image={image}
        deleteHandler={deleteHandler}
        setImagetoCrop={setImagetoCrop}
        setShowCropModal={setShowCropModal}
        isMainImage={isMainImage}
      />
  ));

  // Helper function for reordering array when drag and drop occurs
  const reorder = (list: any[], startIndex: number, endIndex: number) => {
    const result = Array.from(list);
    const [removed] = result.splice(startIndex, 1);
    result.splice(endIndex, 0, removed);
    return result;
  };

  const onSortEnd = ({ oldIndex, newIndex }: {oldIndex: number, newIndex: number}) => {
    const reorderedImages = reorder(
      orderedImages,
      oldIndex,
      newIndex,
    );

    const imagesOrder: number[] = [];

    reorderedImages.forEach((image) => {
      imagesOrder.push(image.id);
    });

    setOrderedImages(reorderedImages);
  };

  return (
    <SortableGallery distance={1} axis="xy" onSortEnd={onSortEnd}>

      {
          orderedImages.map((image, index) => (
            <SortableImage
              key={image.id}
              index={index}
              image={image}
              deleteHandler={deleteHandler}
              setImagetoCrop={setImagetoCrop}
              setShowCropModal={setShowCropModal}
              isMainImage={index === 0}
            />
          ))
      }
    </SortableGallery>
  );
};

export default ProductGallery;
0

There are 0 answers