So I’m a little confused on how client components work. In my project I am trying to create an image uploader, and I need to pull the userId from supabase, the supabase server function, and I need to upload the image to supabase storage using the "userId/filename. So I am trying to create a button or use and input with the onChange prop I’m not able to add the function into the button because it clashes with the server side function. Here’s my code:
import React from 'react';
import { Label } from './ui/label';
import { Input } from './ui/input';
import { createClient } from '@/utils/supabase/server';
import { Button } from './ui/button';
import { useToast } from './ui/use-toast';
import { TestButton } from './button';
const UploadImage = () => {
// const { toast } = useToast();
async function handleUpload (e: React.ChangeEvent<HTMLInputElement>) {
// alert('Uploading image');
const supabase = createClient();
const { data } = await supabase.auth.getUser();
alert(data.user?.id);
let file;
if (e.target.files) {
// alert(`e:${e}`);
file = e.target.files[0];
// alert(`file: ${file.name}`);
}
const userId = await supabase.auth.getUser();
const id = userId.data.user?.id;
alert(userId.data.user);
try {
const { data, error } = await supabase.storage
.from('avatars')
.upload('5ff1e6f3-6974-4398-b329-14d737571129/test', file as File, {
// cacheControl: '3600',
upsert: true,
});
// const { data, error } = await supabase.storage
// .from('avatars')
// .upload(
// '5ff1e6f3-6974-4398-b329-14d737571129/' + file!.name,
// file as File,
// {
// cacheControl: '3600',
// upsert: true,
// }
// );
// alert(data);
if (data) {
alert(data);
alert('successfully uploaded');
// toast({
// title: 'Image Uploaded',
// description: 'Your image was successfully uploaded',
// });
} else if (error) {
// alert(error.message);
}
} catch (e) {
// alert(e);
}
};
return (
<div>
<Label htmlFor="picture">Picture</Label>
<Input
id="file_input"
type="file"
accept="image/*"
onChange={e => {
handleUpload(e);
}}
/>
</div>
);
};
export default UploadImage;
TLDR:
How do I create a client component that needs a server-side functionality, or what’s the best way to go about this situation.
Im sorry if this is vague, I don’t fully understand what’s going on, so bear with me. Thanks
2
Answers
Here's how I completed my code, just in case anyone needs it:
Here's where the function is used for the client component
Create a file called
server/upload.ts
and export asupabaseUpload
method from it. This will be a server action that receives your file viaFormData
, inside the function you can fetch the user securely on the server side and upload the file.On the client side, inside your
handleUpload
function you create a newFormData
object and call the server action to upload the file.