Good day, community. I am developing a registration module with React and Suspabase. I have a form where the user selects an image and it is saved correctly in a supabase bucket. Now I want to make the image show to the user once it is saved in the database that went up, I really don't have much idea how to do this I've never used buckets in supabase and I've already read the documentation but I'm still lost I hope you can help me.
This is the code I have at the momento:
Componente CrudUser.js
import React, { useEffect, useState } from "react";
import { supabase } from "../supabase/client";
import RegisterFormUser from "./RegisterFormUser";
import SignOut from "./SignOut";
import TableUser from "./TableUser";
const CrudUser = () => {
const [db, setDb] = useState({});
const [dataRol, setDataRol] = useState({});
const [nameRol, setNameRol] = useState({});
const [dataUserRol, setDataUserRol] = useState({});
const [dataToEdit, setDataToEdit] = useState(null);
//Operacion de lectura tabla Users
const getUserData = () => {
try {
supabase.auth.getUser().then(async (value) => {
const user = value.data.user;
const { data } = await supabase
.from("users")
.select()
.eq("email", user.email);
setDb(data);
});
} catch (error) {
console.error(error.message);
}
};
//Operacion de lectura tabla Roles
const getRoles = async () => {
try {
const { data } = await supabase.from("roles").select("*");
setDataRol(data);
} catch (error) {
console.error(error);
}
};
//Operación de lectura para traer el rol del usuario logueado
const getUserRole = async () => {
try {
await supabase.auth.getUser().then(async (value) => {
const user = value.data.user;
const { data } = await supabase
.from("users")
.select("roles(nombre)")
.eq("email", user.email);
data.map((el) => el.roles.map((roles) => setNameRol(roles.nombre)));
});
} catch (error) {
console.log(error.message);
}
};
const getDataTabRolesUser = async () => {
try {
const { data } = await supabase.from("users_roles").select("*");
setDataUserRol(data);
} catch (error) {
console.error(error.message);
}
};
useEffect(() => {
getUserData();
getRoles();
getDataTabRolesUser();
}, []);
getUserRole();
const createDataUser = (data) => {
try {
supabase.auth.getUser().then(async (value) => {
const user = value.data.user;
data.user_id = Date.now();
await supabase.from("users").insert({
user_id: data.user_id,
email: user.email,
nombres: data.nombres,
apellidos: data.apellidos,
fecha_nacimiento: data.fecha_nacimiento,
is_active: true,
avatar: data.avatar,
});
console.log("Register added successfully");
setDb([...db, data]);
});
} catch (error) {
console.error(error.message);
}
};
const createRolesUser = async (data) => {
try {
await supabase
.from("users_roles")
.insert({ user_id: data.user_id, rol_id: data.roles });
console.log("Rol added succesfully");
setDataUserRol([...dataUserRol, data]);
} catch (error) {
console.error(error.message);
}
};
const uploadAvatar = async (data) => {
const file = data.infoAvatar;
const fileName = data.avatar;
let { error: uploadError } = await supabase.storage
.from("avatars")
.upload(fileName, file);
if (uploadError) {
throw uploadError;
}
};
const deleteDataUser = async (id) => {
let isDelete = window.confirm("Are you sure to delete your data?");
if (isDelete) {
try {
await supabase.from("users_roles").delete().eq("user_id", id);
await supabase.from("users").delete().eq("user_id", id);
let newData = db.filter((el) => el.user_id !== id);
setDb(newData);
console.log("The record was deleted");
} catch (error) {
console.error(error.message);
}
} else {
return;
}
};
const updateDataUser = async (data, updateFields) => {
const { error } = await supabase
.from("users")
.update(updateFields)
.eq("user_id", data.user_id);
let newData = db.map((el) => (el.user_id === data.user_id ? data : el));
setDb(newData);
if (error) throw error;
console.log(data);
};
const updateRolesUser = async (data, updateFields) => {
const { error } = await supabase
.from("users_roles")
.update(updateFields)
.eq("user_id", data.user_id);
if (error) throw error;
console.log(data);
};
return (
<div>
<div className="grid-1-2">
<RegisterFormUser
data={dataRol}
userData={db}
createDataUser={createDataUser}
createRolesUser={createRolesUser}
dataToEdit={dataToEdit}
updateDataUser={updateDataUser}
updateRolesUser={updateRolesUser}
setDataToEdit={setDataToEdit}
uploadAvatar={uploadAvatar}
/>
<br />
<br />
<TableUser
data={db}
dataRol={nameRol}
setDataToEdit={setDataToEdit}
deleteDataUser={deleteDataUser}
/>
<SignOut />
</div>
</div>
);
};
export default CrudUser;
Component RegisterFormUser.js
import React, { useState, useEffect } from "react";
import { useNavigate } from "react-router-dom";
import { supabase } from "../supabase/client";
const initialForm = {
user_id: null,
nombres: "",
apellidos: "",
fecha_nacimiento: "",
avatar: "",
roles: null,
infoAvatar: "",
};
function RegisterFormUser(props) {
//Props
const {
data,
userData,
createDataUser,
createRolesUser,
dataToEdit,
updateDataUser,
updateRolesUser,
setDataToEdit,
uploadAvatar,
} = props;
//States
const [form, setForm] = useState(initialForm);
const [message, setMessage] = useState();
const [response, setResponse] = useState(null);
const [selectValue, setSelectValue] = useState("");
const [selectPicture, setSelectPicture] = useState("");
//Navigate hook
const navigate = useNavigate();
//Set form Values from dataToEdit
useEffect(() => {
if (dataToEdit) {
setForm(dataToEdit);
} else {
setForm(initialForm);
}
}, [dataToEdit]);
//Redirect to signin if not logged in
useEffect(() => {
supabase.auth.getUser().then((value) => {
if (!value.data.user) {
navigate("/signin");
}
});
}, [navigate]);
//Handle form input changes
const handleChange = (e) => {
setForm({
...form,
[e.target.name]: e.target.value,
});
};
//Handle form submission
const handleSubmit = (e) => {
e.preventDefault();
if (form.user_id === null) {
createDataUser(form);
setMessage("Register added successfully");
setResponse(true);
setTimeout(() => {
setResponse(false);
}, 3000);
setTimeout(() => {
createRolesUser(form);
}, 200);
} else if (form.user_id !== null) {
updateDataUser(form, {
nombres: form.nombres,
apellidos: form.apellidos,
fecha_nacimiento: form.fecha_nacimiento,
});
updateRolesUser(form, {
rol_id: form.roles,
});
}
setSelectValue("");
setSelectPicture("");
handleReset();
};
//Handle form reset
const handleReset = (e) => {
setForm(initialForm);
setSelectValue("");
setSelectPicture("");
setDataToEdit(null);
};
//Handle select changes
const handleSelectChange = (e) => {
setSelectValue(e.target.value);
form.roles = e.target.value;
};
//Handle seleccion pictures
const handleSelectPicture = (e) => {
setSelectPicture(e.target.value);
form.avatar = e.target.files[0].name;
form.infoAvatar = e.target.files[0];
console.log(form.avatar);
console.log(form.infoAvatar);
uploadAvatar(form);
};
return (
<div>
<h1>Additional data</h1>
{/*userData.length > 0 ? console.log(userData[0].avatar) : console.log("empty")*/}
{dataToEdit || userData.length <= 0 ? (
<form onSubmit={handleSubmit}>
<h3>{dataToEdit ? "Edit" : "Add"}</h3>
<label htmlFor="nombres">Name </label>
<input
type="text"
id="nombres"
name="nombres"
onChange={handleChange}
value={form.nombres}
placeholder="Write your Name"
/>
<br />
<br />
<label htmlFor="apellidos">Last names </label>
<input
type="text"
id="apellidos"
name="apellidos"
onChange={handleChange}
value={form.apellidos}
placeholder="Write your last name"
/>
<br />
<br />
<label htmlFor="fecha_nacimiento">birthdate </label>
<input
type="date"
id="fecha_nacimiento"
name="fecha_nacimiento"
onChange={handleChange}
value={form.fecha_nacimiento}
/>
<br />
<br />
<label htmlFor="roles">Roles </label>
<select id="roles" onChange={handleSelectChange} value={selectValue}>
<option value="">Select your role</option>
{data.length > 0 ? (
data.map((el, index) => (
<option key={index} value={el.roles_id}>
{el.nombre}
</option>
))
) : (
<option value="" disabled>
Loading...
</option>
)}
</select>
<br />
<br />
<label> Choose a profile picture</label>
<input
type="file"
id="avatar"
name="avatar"
accept="image/png, image/jpeg"
value={selectPicture}
onChange={handleSelectPicture}
/>
<br />
<br />
<input type="submit" value={dataToEdit ? "Edit" : "Add"} />
<input type="reset" value="Clear" onClick={handleReset} />
</form>
) : (
<h3>Your data</h3>
)}
{response && <p>{message}</p>}
</div>
);
}
export default RegisterFormUser;
In order to display an image, you just have to get its URL and pass it to a img
element.
First, add a imageUrl
state at the top.
const [imageUrl, setImageUrl] = useState()
Then after uploading, get the image URL and set it as the state. This code assumes you are using a public bucket, but you just if you are using a private bucket you just have to change the getPublicUrl
to createSignedUrl
const uploadAvatar = async (data) => {
const file = data.infoAvatar;
const fileName = data.avatar;
let { error: uploadError } = await supabase.storage
.from("avatars")
.upload(fileName, file);
if (uploadError) {
throw uploadError;
}
const { data } = supabase
.storage
.from('avatars')
.getPublicUrl(fileName)
setImageUrl(data.publicUrl)
};
Then somewhere within your UI you just need a img
element with the URL set to imageUrl
state.
<img src={imageUrl} />