Error: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it’s defined in, or you might have mixed up default and named imports.
Check the render method of ImageUpload
.
components/ImageUpload.js
import React ,{ useState } from 'react';
import axios from 'axios';
import {
Drawer,
DrawerClose,
DrawerContent,
DrawerDescription,
DrawerFooter,
DrawerHeader,
DrawerTitle,
DrawerTrigger,
Button
} from "../components/ui/drawer"
export default function ImageUpload() {
const [selectedFile, setSelectedFile] = useState(null);
const [selectedFormat, setSelectedFormat] = useState('');
const [message, setMessage] = useState('');
const [downloadLink, setDownloadLink] = useState('');
const [loadng, setLoading] = useState('');
const handleFileChange = (event) => {
const file = event.target.files[0];
setSelectedFile(file);
};
const handleFormatChange = (event) => {
setSelectedFormat(event.target.value);
};
const handleSubmit = async (event) => {
setLoading(!loadng);
event.preventDefault();
const formData = new FormData();
formData.append('image', selectedFile);
formData.append('text', selectedFormat);
try {
const response = await axios.post('http://localhost:8000/image/', formData, {
headers: {
'Content-Type': 'multipart/form-data',
},
});
setMessage('Image uploaded and converted successfully');
setDownloadLink(response.data.converted_image_url); // Set download link
} catch (error) {
setMessage('Failed to upload and convert image');
}
finally {
setLoading(false)
}
};
const reset = () => {
setSelectedFile(null);
setDownloadLink('');
setMessage('');
setSelectedFormat('');
}
return (
<>
<div className=''>
<h1 className="tw-text-white tw-text-center tw-font-bold tw-text-2xl tw-mb-10">Image Conversion</h1>
<form onSubmit={handleSubmit} className=' xl:tw-w-1/2 lg:tw-w-9/12 tw-mx-auto tw-px-5'>
<div class="tw-flex tw-items-center tw-justify-center tw-w-full">
<label for="dropzone-file" class={`${!selectedFile ? 'tw-flex-col tw-h-64 tw-justify-center hover:tw-bg-yellow-300' : 'tw-bg-yellow-400 tw-h-20 tw-px-5'} tw-flex tw-items-center tw-w-full tw-border-2 tw-border-white tw-border-dashed tw-cursor-pointer tw-bg-yellow-400 `}>
{/* <label for="dropzone-file" className="tw-px-5 tw-flex tw-items-center tw-w-full tw-h-20 tw-border-2 tw-border-gray-300 tw-border-dashed tw-rounded-lg tw-cursor-pointer tw-bg-gray-50 hover:tw-bg-gray-100"> */}
{!selectedFile ?
<div class="tw-flex tw-flex-col tw-items-center tw-justify-center tw-pt-5 tw-pb-6">
<svg class="tw-w-8 tw-h-8 tw-mb-4 tw-text-black" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 20 16">
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 13h3a3 3 0 0 0 0-6h-.025A5.56 5.56 0 0 0 16 6.5 5.5 5.5 0 0 0 5.207 5.021C5.137 5.017 5.071 5 5 5a4 4 0 0 0 0 8h2.167M10 15V6m0 0L8 8m2-2 2 2" />
</svg>
<p class="tw-mb-2 tw-text-sm tw-text-black"><span class="font-semibold">Click to upload</span> or drag and drop</p>
<p class="tw-text-xs tw-text-black">SVG, PNG, JPG or GIF (MAX. 800x400px)</p>
</div> : null}
<h1 className='tw-text-black tw-font-semibold'>{selectedFile && selectedFile.name}</h1>
<input disabled={loadng || downloadLink ? true : false} id="dropzone-file" type="file" class="tw-hidden" accept='image/*' onChange={handleFileChange} />
{selectedFile ?
<div className='tw-w-full tw-flex tw-items-center tw-justify-end tw-gap-5'>
{downloadLink ?
<h1 className='tw-p-3 tw-px-5 tw-border-2 tw-border-black tw-font-bold tw-rounded-lg'>Done</h1>
:
<select value={selectedFormat} onChange={handleFormatChange} className='tw-py-3'>
<option value="">Select format</option>
<option value="png">PNG</option>
<option value="jpg">JPG</option>
<option value="jpeg">JPEG</option>
<option value="webp">WEBP</option>
<option value="bmp">BMP</option>
</select>
}
{!selectedFile || !downloadLink ?
<button disabled={loadng ? true : false} type='submit' className={`tw-transition-all tw-delay-100 tw-font-bold tw-bg-zinc-900
hover:tw-bg-zinc-800 hover:tw-border-dotted hover:tw-border-white hover:tw-border-2 tw-border-2
tw-border-zinc-900 tw-text-white tw-p-5 tw-rounded-xl tw-px-10 tw-flex hover:tw-text-yellow-300`}>
{!loadng ? 'Convert' : <img src='/images/loading.svg' className='tw-invert' />}
</button> : null}
<span class="material-symbols-outlined material-symbols-outlined tw-text-black tw-font-bold
hover:tw-text-white tw-text-3xl hover:tw-drop-shadow-[0_5px_5px_black] tw-transition-all tw-delay-70">
settings
</span>
<div className='tw-flex tw-gap-4 tw-items-center'>
{downloadLink ?
<a href={downloadLink} target='_blank' className='hover:tw-no-underline hover:tw-text-yellow-300 tw-transition-all tw-delay-100 tw-font-bold tw-bg-zinc-900
hover:tw-bg-zinc-800 hover:tw-border-dotted hover:tw-border-white hover:tw-border-2 tw-border-2
tw-border-zinc-900 tw-text-white tw-py-4 tw-rounded-xl tw-px-10 tw-flex'>Download</a>
: null}
<button href={'/'} onClick={reset}>
<span title='Remove File' class="material-symbols-outlined tw-text-black tw-font-bold
hover:tw-text-white tw-text-3xl hover:tw-drop-shadow-[0_5px_5px_black] tw-transition-all tw-delay-70">
cancel
</span>
</button>
</div>
</div>
: null}
</label>
</div>
<p>{message}</p>
{downloadLink && (
<a href={downloadLink} download={downloadLink.split('/').pop()}>
Download Converted Image
</a>
)}
</form>
</div>
<Drawer>
<DrawerTrigger>Open</DrawerTrigger>
<DrawerContent>
<DrawerHeader>
<DrawerTitle>Are you absolutely sure?</DrawerTitle>
<DrawerDescription>This action cannot be undone.</DrawerDescription>
</DrawerHeader>
<DrawerFooter>
<Button>Submit</Button>
<DrawerClose>
<Button variant="outline">Cancel</Button>
</DrawerClose>
</DrawerFooter>
</DrawerContent>
</Drawer>
</>
);
};
components/ui/drawer.js
import * as React from "react"
import { Drawer as DrawerPrimitive } from "vaul"
import { cn } from "../../lib/utils"
const Drawer = ({
shouldScaleBackground = true,
...props
}) => (
<DrawerPrimitive.Root shouldScaleBackground={shouldScaleBackground} {...props} />
)
Drawer.displayName = "Drawer"
const DrawerTrigger = DrawerPrimitive.Trigger
const DrawerPortal = DrawerPrimitive.Portal
const DrawerClose = DrawerPrimitive.Close
const DrawerOverlay = React.forwardRef(({ className, ...props }, ref) => (
<DrawerPrimitive.Overlay
ref={ref}
className={cn("fixed inset-0 z-50 bg-black/80", className)}
{...props} />
))
DrawerOverlay.displayName = DrawerPrimitive.Overlay.displayName
const DrawerContent = React.forwardRef(({ className, children, ...props }, ref) => (
<DrawerPortal>
<DrawerOverlay />
<DrawerPrimitive.Content
ref={ref}
className={cn(
"fixed inset-x-0 bottom-0 z-50 mt-24 flex h-auto flex-col rounded-t-[10px] border border-zinc-200 bg-white dark:border-zinc-800 dark:bg-zinc-950",
className
)}
{...props}>
<div
className="mx-auto mt-4 h-2 w-[100px] rounded-full bg-zinc-100 dark:bg-zinc-800" />
{children}
</DrawerPrimitive.Content>
</DrawerPortal>
))
DrawerContent.displayName = "DrawerContent"
const DrawerHeader = ({
className,
...props
}) => (
<div
className={cn("grid gap-1.5 p-4 text-center sm:text-left", className)}
{...props} />
)
DrawerHeader.displayName = "DrawerHeader"
const DrawerFooter = ({
className,
...props
}) => (
<div className={cn("mt-auto flex flex-col gap-2 p-4", className)} {...props} />
)
DrawerFooter.displayName = "DrawerFooter"
const DrawerTitle = React.forwardRef(({ className, ...props }, ref) => (
<DrawerPrimitive.Title
ref={ref}
className={cn("text-lg font-semibold leading-none tracking-tight", className)}
{...props} />
))
DrawerTitle.displayName = DrawerPrimitive.Title.displayName
const DrawerDescription = React.forwardRef(({ className, ...props }, ref) => (
<DrawerPrimitive.Description
ref={ref}
className={cn("text-sm text-zinc-500 dark:text-zinc-400", className)}
{...props} />
))
DrawerDescription.displayName = DrawerPrimitive.Description.displayName
export {
Drawer,
DrawerPortal,
DrawerOverlay,
DrawerTrigger,
DrawerClose,
DrawerContent,
DrawerHeader,
DrawerFooter,
DrawerTitle,
DrawerDescription,
}
I am new to next.js. any help would be appreciated.
i am trying to use shandcn drawer component in my component. but getting the error when i click on the open button.