cloudinary-community / next-cloudinary

⚡️ High-performance image delivery and uploading at scale in Next.js powered by Cloudinary.
https://next.cloudinary.dev
MIT License
253 stars 75 forks source link

[Bug] r.current is undefined on CldUploadWidget #330

Closed LegrainAnthony closed 11 months ago

LegrainAnthony commented 1 year ago

Bug Report

r.current is undefined

Describe the bug

I generate my Cloudinary widgets in a loop, but sometimes one of the Cloudinary widgets generated by the loop throws an error "r.current is undefined" when I click on it, and it happens randomly

Steps To Reproduce the error

1 - Generate the cldwidgets in a loop 2 - Click on one of the cldwidgets 3 - r.current is undefined

(This occurs randomly and not on every cldwidgets)

colbyfayock commented 1 year ago

@LegrainAnthony any chance you have an example, such as a code sandbox?

i suspect there may be an issue with all of the various instances trying to load and Next Script trying to manage them all

if that's the case, seeing something similar on the Video Player side:

https://github.com/colbyfayock/next-cloudinary/issues/279

LegrainAnthony commented 1 year ago

Hi. thanks for the response

Here the loop where my cloudinary components is called

return images.map((image, index) => (
    <div
        className="gallery-item"
        key={index}
        onClick={() => {
            if (imagesArray.length > 1) {
                setIndex(index);
            }
        }}
    >
        <CloudinaryWidget
            key={reRenderCldWidget}
            uploadCallBack={uploadCallBackEvent}
            type={image.type}
            order={image.type !== "fotos-coverPic" ? image.order : null}
            deleteFunc={deleteFunc}
            croppingAspectRatio={image.type === "fotos-coverPic" ? 2.1 : 1.14}
            currentPublicId={image.currentPublicId}
            minImageWidth={image.type === "fotos-coverPic" ? 1000 : 600}
            minImageHeight={500}
            text="Télécharger une photo"
            folder={`xxxxxxx-${values.event_id}`}
            newPublicId={image.type === "xxxxxxx" ? `xxxxxxx-` : `xxxxxxxx`}
            widgetType="button"
            trashable={false}
            locale={locale}
            index={index}
            origin={origin}
            setReRenderCldWidget={setReRenderCldWidget}
        />
    </div>
));

and here the CldUploadWidget in the component


    <CldUploadWidget
        options={{
            cloudName: process.env.CLOUDINARY_CLIENT_NAME,
            cropping: true,
            croppingAspectRatio: croppingAspectRatio,
            croppingShowBackButton: true,
            showSkipCropButton: false,
            folder: folder,
            publicId: newPublicId,
            language: locale,
            text: cloudinaryTexts,
            minImageWidth: minImageWidth,
            minImageHeight: minImageHeight,
            maxImageWidth: 2500,
            maxImageFileSize: 15250000,
            validateMaxWidthHeight: true,
            sources: ["local", "facebook", "instagram", "dropbox", "google_drive"],
            styles: {
                palette: {
                    window: "#FFFFFF",
                    windowBorder: "#90A0B3",
                    tabIcon: "#FF0054",
                    menuIcons: "#5A616A",
                    textDark: "#000000",
                    textLight: "#FFFFFF",
                    link: "#FF0054",
                    action: "#00277C",
                    inactiveTabIcon: "#0E2F5A",
                    error: "#FF0000",
                    inProgress: "#FF0054",
                    complete: "#20B832",
                    sourceBg: "#E4EBF1"
                },
                fonts: {
                    default: {
                        active: true
                    }
                }
            },
            uploadPreset: process.env.CLOUDINARY_UPLOAD_PRESET
        }})
LegrainAnthony commented 1 year ago

Lol sorry, first time i do a issue.

I know that this code is not very useful, but the component is very simple. I retrieve images from a source, and then I loop through them. If there's an image, I display it (no problem there). If I don't have an image, I display the Cloudinary widget (usually no issues with it). However, from time to time and randomly, the Cloudinary widget returns 'r.current is undefined' and doesn't open.

The only solution to make it work again is to perform a page render to re-run the loop and recreate the cldWidget.

but for now i don't know how handle this error.

colbyfayock commented 1 year ago

hey @LegrainAnthony the latest release should have a fix that may help address this, in particular it handles cleaning up old instances of the widget as well as maintaining individual versions of the script being loaded to more reliably load a bunch of different widget instances

can you give it a try and see if it resolves your issue?

version 5.4.0

LegrainAnthony commented 11 months ago

Hello,

I apologize for the delayed response as I am currently in an apprenticeship program and couldn't test this earlier. After updating next-cloudinary, I'm still encountering an issue which might be related to my handling of Cloudinary instances.

I would like the Cloudinary widget to reset its state after an error or a successful upload, enabling immediate reuse. However, I haven't found a method in the Cloudinary documentation to reset the state, except for destroying and recreating the widget.

Currently, the close method keeps the widget in a "downloading" state after a successful image upload. In case of an error, it maintains its error queue.

The issue might stem from how I'm handling the recreation of the widget. Below are code snippets illustrating my current approach.

    const [cldRenderKey, setCldRenderKey] = useState(Date.now());

    <CldUploadWidget
            key={cldRenderKey}
                   // options and uploadPreset...   
            onOpen={(widget) => {
            widget.update({
                publicId: newPublicId + Date.now()
            });
        }}
        onUpload={(result, widget) => {
            handleUpload(result, widget);
        }}
        onClose={(widget) => {
            setCldRenderKey(Date.now());
        }}
        onQueuesEnd={(result, options) => {
            if (result.info.files[0].failed) {
                if (result.info.files[0].statusText.includes("are bigger than the maximum")) {
                    message.error({ content: `L'image est trop grande. Taille maximal : 5000 px`, duration: 5 });
                }
                if (result.info.files[0].statusText.includes(`are smaller than the minimum`)) {
                    message.error({ content: `L'image est trop petite. Taille minimal                                 ${minImageWidth}x${minImageHeight} `, duration: 5 });
                }
                options.widget.destroy();
                         setCldRenderKey(Date.now());
                }
            }}
                       >
            {({ cloudinary, error, isLoading, results, open, widget }) => {
                // JSX...
            }}
        </CldUploadWidget>

Any guidance or suggestions on how to properly reset the widget's state would be greatly appreciated.

Thank you!

colbyfayock commented 11 months ago

just to be clear, this isn't related to the original issue correct? this is something new? do you have any updates or are you still running into the same issue that was originally posted?

as far as resetting the widget state, that's an interesting one, can you share a screenshot of the experience that you're seeing? I'm trying to understand what loading and error state you're seeing. if you're referring to simply uploading an image, closing the widget, and opening it again, there may have been a bug previously that was causing this issue, are you using the latest version of the library? 5.7.0 => https://www.npmjs.com/package/next-cloudinary/v/5.7.0

if you go to the docs site, you should be able to reproduce uploading an image twice successfully: https://next.cloudinary.dev/clduploadwidget/basic-usage

colbyfayock commented 11 months ago

given i believe this other issue is unrelated to the original Issue, I'm going to close this, but please feel free to create a new Issue with information on the other if you can reproduce on the latest version, or if this issue still isn't addressed, I can re-open it