lightGallery icon indicating copy to clipboard operation
lightGallery copied to clipboard

React LightGallery component always create a new `LightGallery` instance on re-render

Open darkyzhou opened this issue 2 years ago • 3 comments

Description

My LightGallery component always create a new LightGallery instance on each render.

截屏2022-10-18 21 00 53

Steps to reproduce

  1. Use Vite React template.
  2. Install the library.
  3. My codes are as below. When setList() is called, LightGallery always create a new LightGallery instance.
const LIGHT_GALLERY_PLUGINS = [lgZoom, lgRotate]
const LIGHT_GALLERY_MOBILE_SETTINGS = {
  download: true,
  controls: false,
  flipHorizontal: false,
  flipVertical: false,
  rotateRight: false,
}

function MyComponent() {
  const [list, setList] = useState([])
  return <LightGallery
    selector="[data-my-image]"
    easing="ease-in-out"
    speed={300}
    startAnimationDuration={100}
    plugins={LIGHT_GALLERY_PLUGINS}
    download={true}
    mobileSettings={LIGHT_GALLERY_MOBILE_SETTINGS}
    enableSwipe={true}
    enableDrag={true}
  >
    {list.map(item => <img key={item.key} data-my-image="" src={item.src} />)}
  </LightGallery>
}

Environment

  • Browser and version - Edge 106.0.1370.34 arm64
  • OS - macOS 12.6
  • lightGallery version - 2.6.1

Additional context

I think the bug is related to the usage of restProps:

// Lightgallery.tsx

// ...

const LG: React.FC<LightGalleryProps> = ({
    children,
    // ...
    onFlipVertical,
    ...restProps
}: LightGalleryProps) => {
    const $lg = React.useRef<HTMLDivElement>(null);

    const registerEvents = // ...

    React.useEffect(() => {
        registerEvents();
        const lightGallery = LightGallery(
            ($lg.current as unknown) as HTMLElement,
            restProps,
        );
        return function cleanup() {
            lightGallery.destroy();
        };
    // ⚠️⚠️⚠️
    // Here the reference `resetProps` ALWAYS differ on each render.
    // By temporarily removing it, the bug disappears. So a possible solution
    // might be manually do a deep check on the properties of `restProps`
    // ⚠️⚠️⚠️
    }, [registerEvents, restProps]);

    return // ...
};
export default LG;

darkyzhou avatar Oct 18 '22 13:10 darkyzhou

Probably we could use something like react-fast-compare?

Poky85 avatar Jan 17 '23 10:01 Poky85

Change in effect dependencies has been introduced in 2.6.0, so temporary fix is downgrade to 2.5.0

Poky85 avatar Jan 18 '23 14:01 Poky85

same the issue. I using inline and it re-render when i update state

gamestap99 avatar May 08 '23 07:05 gamestap99