简体   繁体   中英

Implementing Cloudinary Product Gallery in Next.js

I am trying to use the Cloudinary Product Gallery in my eCommerce - Next.js project, but am having a difficult time putting it together.

Here is Cloudinary Product Gallery: https://cloudinary.com/documentation/product_gallery

The error I am getting: Cannot read property 'galleryWidget' of undefined . Let me know what I am doing wrong.

file - _document.js

import Document, { Html, Head, Main, NextScript } from 'next/document';

class MyDocument extends Document {
  render() {
    return (
      <Html>
        <Head />
        <body>
          <script
            src="https://product-gallery.cloudinary.com/all.js"
            type="text/javascript"
          ></script>
          <Main />
          <NextScript />
        </body>
      </Html>
    );
  }
}

export default MyDocument;

file - SingleProduct.jsx

import React, { useRef } from 'react';

const SingleProduct = ({ product }) => {
  const { slug } = product;
  const cloudnaryGalleryRef = useRef(null);

  if (!cloudnaryGalleryRef.current) {
    cloudnaryGalleryRef.current = window.cloudinary
      .galleryWidget({
        container: '#my-gallery',
        cloudName: 'cloudName',
        carouselStyle: 'thumbnails',
        thumbnailProps: {
          width: 75,
          height: 75,
          spacing: 4,
          navigationColor: 'green',
        },
        mediaAssets: [{ tag: slug }],
      })
      .render();
  }

  return <div id="my-gallery"></div>;
};

export default SingleProduct;

Assuming there's no problem with your script, you need to check if window available before executing the function..

eg

if (typeof window !== 'undefined') {
    ..... window.cloudinary.galleryWidget(.....)
}

You will notice this will occur very frequently in nextjs apps, and you need to include these necessary checks since next.js in most cases are server side generated, and until pages are loaded in browser, window is not defined.

Here is an working solution

import React, { useRef } from 'react';
const SingleProduct = ({ product }) => {
  const { slug } = product;
  const [loaded, setLoaded] = useState(false);

  useEffect(() => {
    const scriptTag = document.createElement('script');
    scriptTag.src = 'https://product-gallery.cloudinary.com/all.js';
    scriptTag.addEventListener('load', () => setLoaded(true));
    document.body.appendChild(scriptTag);
  }, []);

  const cloudnaryGalleryRef = useRef(null);

  useEffect(() => {
    if (!loaded) return;
    const myGallery = window.cloudinary.galleryWidget({
      container: '#my-gallery',
      cloudName: 'dhvi46rif',
      carouselStyle: 'thumbnails', // default value: included for clarity
      thumbnailProps: {
        width: 75,
        height: 75,
        spacing: 4,
        navigationColor: 'green',
      },
      mediaAssets: [{ tag: slug }],
    });
    if (!cloudnaryGalleryRef.current && typeof window !== 'undefined') {
      cloudnaryGalleryRef.current = myGallery.render();
    }
    return () => {
      cloudnaryGalleryRef.current = myGallery.destroy(); // Important To avoid memory leaks and performance issues, make sure to use the destroy method before removing the Product Gallery widget container element from your DOM.
    };
  }, [loaded, slug]);

  return <div id="my-gallery" />;
};

export default SingleProduct;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM