在 Next.js 中实施 Cloudinary Product Gallery
Implementing Cloudinary Product Gallery in Next.js
我正在尝试在我的电子商务 - Next.js 项目中使用 Cloudinary Product Gallery,但很难将其组合在一起。
这里是 Cloudinary 产品库:https://cloudinary.com/documentation/product_gallery
我得到的错误: Cannot read property 'galleryWidget' of undefined
。让我知道我做错了什么。
文件 - _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;
文件 - 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;
假设你的脚本没有问题,你需要在执行函数之前检查window是否可用..
例如
if (typeof window !== 'undefined') {
..... window.cloudinary.galleryWidget(.....)
}
您会注意到这在 nextjs 应用程序中会非常频繁地发生,并且您需要包括这些必要的检查,因为 next.js 在大多数情况下是服务器端生成的,并且在浏览器中加载页面之前,window
未定义。
这是一个可行的解决方案
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;
我正在尝试在我的电子商务 - Next.js 项目中使用 Cloudinary Product Gallery,但很难将其组合在一起。
这里是 Cloudinary 产品库:https://cloudinary.com/documentation/product_gallery
我得到的错误: Cannot read property 'galleryWidget' of undefined
。让我知道我做错了什么。
文件 - _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;
文件 - 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;
假设你的脚本没有问题,你需要在执行函数之前检查window是否可用..
例如
if (typeof window !== 'undefined') {
..... window.cloudinary.galleryWidget(.....)
}
您会注意到这在 nextjs 应用程序中会非常频繁地发生,并且您需要包括这些必要的检查,因为 next.js 在大多数情况下是服务器端生成的,并且在浏览器中加载页面之前,window
未定义。
这是一个可行的解决方案
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;