react-google-recaptcha-v3
react-google-recaptcha-v3 copied to clipboard
Nextjs upload bug
When using Nextjs and uploading lots of content, recaptcha seems to be added multiple times to DOM and eventually crashes the app.
Hi @fred-boink, without an example of your code I will not be able to assist or tell what's wrong.
Hi @t49tran
in my app.tsx
<GoogleReCaptchaProvider
scriptProps={{ async: true, defer: true, appendTo: 'body' }}
reCaptchaKey={process.env.NEXT_PUBLIC_GOOGLE_CAPTCHA_KEY}
useEnterprise
>
<ToastProvider
placement="top-center"
components={{ Toast: Toaster }}
autoDismiss
>
<IntercomProvider
appId={process.env.NEXT_PUBLIC_INTERCOM_APP_ID}
>
<LoginOverlayProvider>
<UnsupportedBrowserGuard>
<DesktopGuard>
<AuthProvider>
<Component {...pageProps} />
</AuthProvider>
</DesktopGuard>
</UnsupportedBrowserGuard>
</LoginOverlayProvider>
</IntercomProvider>
</ToastProvider>
</GoogleReCaptchaProvider>
Then we have inputs for uploading files in another component
const UploadPostButton = ({ postDraft, saveDraft }) => {
const fileUpload = useRef<HTMLInputElement>(null);
const { uploadFile } = useUploadStore();
const onFileSelected = async (
fileUploadEvent: ChangeEvent<HTMLInputElement>
) => {
const { files } = fileUploadEvent.target;
for (let i = 0; i < files.length; i++) {
const file: File = files[i];
let postItem: DraftPostItemType;
let fileToUpload;
if (file.type.split('/')[0] === PostItemTypes.VIDEO) {
const isMultiPart = IsMultiPart(file);
const { vaultId, vaultVideoPresignedUrl, key, uploadId } =
await getVideoSignedUrl(file.name, isMultiPart);
fileToUpload = {
file,
presignedUrl: vaultVideoPresignedUrl,
key,
uploadId,
vaultId
};
postItem = new VideoDraftPostItem({
vaultId,
status: PostItemStatuses.LOCAL,
uploadedFileName: file.name
});
await postItem.setEnd(file);
await postItem.setLocalThumbnail(file);
} else {
const { vaultId, vaultImagePresignedUrl } =
await getImageSignedUrl(file.name);
fileToUpload = {
file,
presignedUrl: vaultImagePresignedUrl,
vaultId
};
postItem = new ImageDraftPostItem({
vaultId,
status: PostItemStatuses.LOCAL,
uploadedFileName: file.name
});
await postItem.cropImageFromFile(file);
}
await postItem.setMediaUrlFromFile(file);
// if no post cover set
// first post item as post cover
if (!postDraft.postCover || postDraft.postItems.length === 0) {
postDraft.postCover = postItem;
}
postDraft.postItems = postDraft.postItems.concat(postItem);
uploadFile(fileToUpload);
}
await saveDraft(postDraft);
};
return (
<>
<div
className={classNames(
'flex',
'items-center',
'justify-center',
// 'py-15',
// 'flex-1/4',
'w-full',
'bg-white',
'bg-opacity-5'
)}
>
<div
className={classNames(
'flex',
'justify-center',
'py-40',
'pwa:pb-safe-15',
'space-x-20'
)}
>
<div>
<input
type="file"
// heic must be explicitely added
accept="image/*,video/*,image/heic"
ref={fileUpload}
hidden
multiple
onChange={(e) => onFileSelected(e)}
/>
<button
type="button"
onClick={() => fileUpload.current.click()}
className={classNames(
'flex',
'items-center',
'flex-col'
)}
>
<div
className={classNames(
'flex',
'items-center',
'justify-center',
'rounded-full',
'wh-80',
'bg-blue-700'
)}
>
<Add
className={classNames(
'wh-32',
'text-gray-700'
)}
/>
</div>
{/* <p
className={classNames(
'mt-8',
'text-12',
'text-blue-700',
'text-center'
)}
>
Add
</p> */}
</button>
</div>
{/* <Link href="/posts?status=draft">
<a
className={classNames(
'flex',
'items-center',
'flex-col'
)}
>
<div
className={classNames(
'flex',
'items-center',
'justify-center',
'rounded-full',
'wh-80',
'bg-orange-700'
)}
>
<Pencil2
className={classNames(
'text-gray-700',
'wh-32'
)}
/>
</div>
<span
className={classNames(
'mt-8',
'text-12',
'text-orange-700',
'text-center'
)}
>
Drafts
</span>
</a>
</Link> */}
</div>
</div>
</>
);
};
When I have the google recaptcha provider around my app, and multiple uploads going my app completely crashes. If I comment out recaptcha provider, it works perfectly. Not sure if its doing something weird with upload inputs.
Hi @t49tran
in my app.tsx
<GoogleReCaptchaProvider scriptProps={{ async: true, defer: true, appendTo: 'body' }} reCaptchaKey={process.env.NEXT_PUBLIC_GOOGLE_CAPTCHA_KEY} useEnterprise > <ToastProvider placement="top-center" components={{ Toast: Toaster }} autoDismiss > <IntercomProvider appId={process.env.NEXT_PUBLIC_INTERCOM_APP_ID} > <LoginOverlayProvider> <UnsupportedBrowserGuard> <DesktopGuard> <AuthProvider> <Component {...pageProps} /> </AuthProvider> </DesktopGuard> </UnsupportedBrowserGuard> </LoginOverlayProvider> </IntercomProvider> </ToastProvider> </GoogleReCaptchaProvider>
Then we have inputs for uploading files in another component
const UploadPostButton = ({ postDraft, saveDraft }) => { const fileUpload = useRef<HTMLInputElement>(null); const { uploadFile } = useUploadStore(); const onFileSelected = async ( fileUploadEvent: ChangeEvent<HTMLInputElement> ) => { const { files } = fileUploadEvent.target; for (let i = 0; i < files.length; i++) { const file: File = files[i]; let postItem: DraftPostItemType; let fileToUpload; if (file.type.split('/')[0] === PostItemTypes.VIDEO) { const isMultiPart = IsMultiPart(file); const { vaultId, vaultVideoPresignedUrl, key, uploadId } = await getVideoSignedUrl(file.name, isMultiPart); fileToUpload = { file, presignedUrl: vaultVideoPresignedUrl, key, uploadId, vaultId }; postItem = new VideoDraftPostItem({ vaultId, status: PostItemStatuses.LOCAL, uploadedFileName: file.name }); await postItem.setEnd(file); await postItem.setLocalThumbnail(file); } else { const { vaultId, vaultImagePresignedUrl } = await getImageSignedUrl(file.name); fileToUpload = { file, presignedUrl: vaultImagePresignedUrl, vaultId }; postItem = new ImageDraftPostItem({ vaultId, status: PostItemStatuses.LOCAL, uploadedFileName: file.name }); await postItem.cropImageFromFile(file); } await postItem.setMediaUrlFromFile(file); // if no post cover set // first post item as post cover if (!postDraft.postCover || postDraft.postItems.length === 0) { postDraft.postCover = postItem; } postDraft.postItems = postDraft.postItems.concat(postItem); uploadFile(fileToUpload); } await saveDraft(postDraft); }; return ( <> <div className={classNames( 'flex', 'items-center', 'justify-center', // 'py-15', // 'flex-1/4', 'w-full', 'bg-white', 'bg-opacity-5' )} > <div className={classNames( 'flex', 'justify-center', 'py-40', 'pwa:pb-safe-15', 'space-x-20' )} > <div> <input type="file" // heic must be explicitely added accept="image/*,video/*,image/heic" ref={fileUpload} hidden multiple onChange={(e) => onFileSelected(e)} /> <button type="button" onClick={() => fileUpload.current.click()} className={classNames( 'flex', 'items-center', 'flex-col' )} > <div className={classNames( 'flex', 'items-center', 'justify-center', 'rounded-full', 'wh-80', 'bg-blue-700' )} > <Add className={classNames( 'wh-32', 'text-gray-700' )} /> </div> {/* <p className={classNames( 'mt-8', 'text-12', 'text-blue-700', 'text-center' )} > Add </p> */} </button> </div> {/* <Link href="/posts?status=draft"> <a className={classNames( 'flex', 'items-center', 'flex-col' )} > <div className={classNames( 'flex', 'items-center', 'justify-center', 'rounded-full', 'wh-80', 'bg-orange-700' )} > <Pencil2 className={classNames( 'text-gray-700', 'wh-32' )} /> </div> <span className={classNames( 'mt-8', 'text-12', 'text-orange-700', 'text-center' )} > Drafts </span> </a> </Link> */} </div> </div> </> ); };
When I have the google recaptcha provider around my app, and multiple uploads going my app completely crashes. If I comment out recaptcha provider, it works perfectly. Not sure if its doing something weird with upload inputs.
you shouldn't use it in your app.tsx for Nextjs. You should create HOC and wrap each page in it or you will get overloads every time.