I'm using cloudinary for users to be able to upload an avatar image with next js and I've set a controller file in the backend that triggers the function to edit profile data with mongoDB and node js. The url of the cloudinary image is supposed to be received by the controller as part of the object called "datosActualizados" when handleSubmit is triggered (the state is called "urlImagen". However, the state is not received correctly the first time but the second one. I though it could be that the put request was getting executed before the state is set, so I tried adding a setTimeOut function to it, but the issue persists. Any help would be greatly appreciated:
const [urlImagen, setUrlImagen] = useState(auth.imagen)
try {
// Eliminar avatar anterior de Cloudinary
const timestamp = new Date().getTime();
const signature = generateSHA1(`public_id=${process.env.CLOUDINARY_UPLOAD_PRESET}/${usuarioID}×tamp=${timestamp}${process.env.CLOUDINARY_API_SECRET}`);
const cloudinaryResponse = await clienteAxios.post(`https://api.cloudinary.com/v1_1/${process.env.CLOUDINARY_CLOUD_NAME}/image/destroy`, {
public_id: `${process.env.CLOUDINARY_UPLOAD_PRESET}/${usuarioID}`,
signature: signature,
api_key: process.env.CLOUDINARY_API_KEY,
timestamp: timestamp
});
if (imagen) {
// Subir nuevo avatar a Cloudinary
const image = new FormData()
image.append('file', imagen)
image.append('upload_preset', process.env.CLOUDINARY_UPLOAD_PRESET)
image.append('public_id', usuarioID)
const response = await clienteAxios.post(`https://api.cloudinary.com/v1_1/${process.env.CLOUDINARY_CLOUD_NAME}/image/upload`, image)
setUrlImagen(response.data.secure_url)
}
const fechaNacimiento = `${dia.toString().padStart(2, '0')}-${mes.toString().padStart(2, '0')}-${year.toString()}`;
const datosActualizados = {
nombre,
apellido,
usuarioID,
email,
descripcion,
fechaNacimiento,
imagen: urlImagen
};
const { data } = await clienteAxios.put(`/usuarios/perfil/${auth._id}`, datosActualizados)
setAlertaVisible(true)
setAlerta({
msg: data.msg,
error: false,
})
setTimeout(() => {
setAlertaVisible(false)
}, 3000);
} catch (error) {
console.log(error)
setAlertaVisible(true)
setAlerta({
msg: error.response.data.msg,
error: true,
})
And here's the code of the usuarioController file in the backend:
const editarPerfil = async (req, res, next) => {
const { nombre, apellido, email, descripcion, fechaNacimiento, usuarioID, imagen } = req.body;
try {
console.log(imagen)
// Busca el usuario por su ID y actualiza los campos correspondientes
let usuarioActualizado = await Usuario.findByIdAndUpdate(req.params.id,
{
nombre,
apellido,
email,
descripcion,
fechaNacimiento,
usuarioID,
imagen
},
{ new: true } // Devuelve el usuario actualizado
);
res.json({ msg: "Perfil actualizado correctamente", visible: true, usuarioActualizado });
} catch (err) {
console.log(err);
const error = new Error("Error al editar el perfil del usuario")
res.status(500).json({ msg: error.message, visible: true });
}
};
The urlImagen state is not received by the controller the first time handleSubmit function is triggered, but works the second time. I need the state to be received by the controller so users can update profile data, including url of the cloudinary avatar image