Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ const CldUploadWidget = ({
const uploadWidgetId = useUploadWidgetId();
const cloudinary: CldUploadWidgetCloudinaryInstance = useRef();
const widget: CldUploadWidgetWidgetInstance = useRef();
const isMounted = useRef(false);

const [error, setError] = useState<CloudinaryUploadWidgetError | undefined>(undefined);
const [results, setResults] = useState<CloudinaryUploadWidgetResults | undefined>(undefined);
Expand Down Expand Up @@ -130,6 +131,8 @@ const CldUploadWidget = ({
*/

function handleOnLoad() {
if ( !isMounted.current ) return;

setIsScriptLoading(false);

if ( !cloudinary.current ) {
Expand All @@ -140,14 +143,16 @@ const CldUploadWidget = ({
// to trigger widget creation. Optional.

triggerOnIdle(() => {
if ( !widget.current ) {
if ( isMounted.current && !widget.current ) {
widget.current = createWidget();
}
});
}

useEffect(() => {
isMounted.current = true;
return () => {
isMounted.current = false;
widget.current?.destroy();
widget.current = undefined;
}
Expand Down
55 changes: 55 additions & 0 deletions next-cloudinary/tests/nextjs-app/app/test-widget/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
"use client";

import { useState } from 'react';
import { CldUploadWidget } from '../../../../';

export default function TestWidget() {
const [mounted, setMounted] = useState(true);
const [mountCount, setMountCount] = useState(1);

function toggle() {
setMounted(false);
setTimeout(() => {
setMounted(true);
setMountCount((c) => c + 1);
}, 300);
}

return (
<div style={{ padding: '2em', fontFamily: 'sans-serif' }}>
<h1>CldUploadWidget — unmount/remount test</h1>
<p>
Click <strong>Remount widget</strong> to unmount and remount the widget.
After each remount, open the browser DevTools → Elements panel and check
that there is only <strong>one</strong> Cloudinary Upload Widget iframe
in the DOM (look for <code>id</code> starting with <code>cloudinary-widget</code>).
</p>
<p>Mount count: <strong>{mountCount}</strong></p>

<div style={{ marginBottom: '1em' }}>
<button onClick={toggle} style={{ marginRight: '1em' }}>
Remount widget
</button>
</div>

{mounted && (
<CldUploadWidget uploadPreset="next-cloudinary-unsigned">
{({ open }) => (
<button onClick={() => open()}>
Open Upload Widget
</button>
)}
</CldUploadWidget>
)}

<hr style={{ margin: '2em 0' }} />
<h2>How to verify</h2>
<ol>
<li>Open DevTools → Elements (or Inspector)</li>
<li>Search for <code>cloudinary-widget</code> in the DOM</li>
<li>Click <strong>Remount widget</strong> several times</li>
<li>Confirm there is always exactly one iframe — not one per remount</li>
</ol>
</div>
);
}