sachinchoolur / lightGallery

A customizable, modular, responsive, lightbox gallery plugin.
https://www.lightgalleryjs.com/
Other
6.56k stars 1.29k forks source link

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

Open darkyzhou opened 2 years ago

darkyzhou commented 2 years ago

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 => )} }

Environment

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;
Poky85 commented 1 year ago

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

Poky85 commented 1 year ago

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

gamestap99 commented 1 year ago

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