From 0 to production tutorial help with uploadthing implementation - UploadButton stuck on loading
So I am following Theo's guide to learn nextjs and react a bit, coming from sveltekit, but I am having an issue where the UploadButton component from uploadthing is stuck on loading instead of showing 'choose file' like in theo's video.
The button is imported from ~/utils/uploadthing where I have the import code for it and it's not showing me any errors in VScode, but on the server I get this error which I assume is the issue
"Warning: Only plain objects can be passed to Client Components from Server Components. URL objects are not supported.
<... endpoint=... url={URL}>"
I passed imageUploader as an endpoint like in the tutorial <UploadButton endpoint="imageUploader" /> and in the uploadthing docs, so I am not sure what I am doing wrong, any help would be appreciated and if more info is needed just let me know.
4 Replies
can you provide paste both your component and server code ?
For sure - thanks for helping me look into it
import {
generateUploadButton,
generateUploadDropzone,
} from "@uploadthing/react";
import type { OurFileRouter } from "~/app/api/uploadthing/core";
export const UploadButton = generateUploadButton<OurFileRouter>();
export const UploadDropzone = generateUploadDropzone<OurFileRouter>();
core.ts
import { createUploadthing, type FileRouter } from "uploadthing/next";
import { UploadThingError } from "uploadthing/server";
const f = createUploadthing();
const auth = (req: Request) => ({ id: "fakeId" }); // Fake auth function
// FileRouter for your app, can contain multiple FileRoutes
export const ourFileRouter = {
// Define as many FileRoutes as you like, each with a unique routeSlug
imageUploader: f({ image: { maxFileSize: "4MB" } })
// Set permissions and file types for this FileRoute
.middleware(async ({ req }) => {
// This code runs on your server before upload
const user = auth(req);
// If you throw, the user will not be able to upload
if (!user) throw new UploadThingError("Unauthorized");
// Whatever is returned here is accessible in onUploadComplete as
metadata
return { userId: user.id };
})
.onUploadComplete(async ({ metadata, file }) => {
// This code RUNS ON YOUR SERVER after upload
console.log("Upload complete for userId:", metadata.userId);
console.log("file url", file.url);
// !!! Whatever is returned here is sent to the clientside
onClientUploadComplete callback
return { uploadedBy: metadata.userId };
}),
} satisfies FileRouter;
export type OurFileRouter = typeof ourFileRouter;
Let me know if I missed something or you need something else?Provide the code where you actually render the button.
import { SignedIn, SignedOut, SignInButton, UserButton } from "@clerk/nextjs";
import { UploadButton } from "~/utils/uploadthing";
import { UpdatePrefs } from "./updateprefs";
export function TopNav() {
return (
<nav className="flex items-center justify-between flex-wrap bg-slate-600 p-6 w-full text-white text-xl font-semibold border-b border-slate-400">
<div>Gallery</div>
<div className="flex flex-row ">
<SignedOut>
<SignInButton />
</SignedOut>
<SignedIn>
<UploadButton
endpoint="imageUploader"></UploadButton>
<UserButton />
<UpdatePrefs />
</SignedIn>
</div>
</nav>
);
}
Just this