not uploading a file to firebase in react - javascript

I'm trying to upload a file to the firebase. Here is the code I used to do it in react. I'm a beginner to firebase and I'm unable to sort out what's wrong here.
import {Component} from "react";
import React from "react";
import "./style.scss";
import Add from "../../assets/imgs/addAvatar.png";
import {createUserWithEmailAndPassword, updateProfile } from "firebase/auth";
import {auth, db } from "../../firebase/firebase";
import {ref, uploadBytesResumable, getDownloadURL, getStorage} from "firebase/storage";
class Register extends Component {
constructor(props) {
super(props);
this.state = {
formData:{
name: "",
email: "",
password: "",
file: "",
}
}
}
handleSubmit = async (e) =>{
const displayName = this.state.formData.name;
const email = this.state.formData.email;
const password = this.state.formData.password;
const file = this.state.formData.file;
try {
const res = await createUserWithEmailAndPassword(auth, email, password);
const storage = getStorage();
const storageRef = ref(storage,displayName);
const uploadTask = uploadBytesResumable(storageRef, file);
uploadTask.on(
(error) => {
// Handle unsuccessful uploads
},
() => {
getDownloadURL(uploadTask.snapshot.ref).then(async (downloadURL) => {
await updateProfile(res.user,{
displayName,
photoURL: downloadURL
});
await db.collection("users").doc(res.user.uid).set({
uid:res.user.uid,
displayName,
email,
photoURL: downloadURL
})
});
}
);
}
catch (err) {
console.error(err);
}
}
render() {
return (
<div className="container">
<div className="containerWrapper">
<div className="titleContainer">
<span className="heading">Din-Chat</span>
<span className="title">Register</span>
</div>
<form>
<input type="text" placeholder="Name:"
onChange={(e) => {
let data = this.state.formData;
data.name = e.target.value;
this.setState({data})
}}
/>
<input type="email" placeholder="E-mail:"
onChange={(e) => {
let data = this.state.formData;
data.email = e.target.value;
this.setState({data})
}}
/>
<input type="password" placeholder="Password:"
onChange={(e) => {
let data = this.state.formData;
data.password = e.target.value;
this.setState({data})
}}
/>
<input type="file" id="file" style={{display:'none'}}
onChange={(e) => {
let data = this.state.formData;
data.file = e.target.value;
this.setState({data})
}}
/>
<label htmlFor="file">
<div className="label" style={{display:'flex'}}>
<img src={Add} alt="ADD" width="40px" style={{marginLeft:'5px',cursor:'pointer'}}/>
<span style={{display:'flex',marginLeft:'5px',alignItems:'center',cursor:'pointer'}}>Add an image</span>
</div>
</label>
</form>
<div className="btnContainer">
<button type="submit" onClick={() =>{
this.handleSubmit();
}}>Register</button>
</div>
<p>Do you have an Account? Login</p>
</div>
</div>
)
}
}
export default Register;
In this file const uploadTask = uploadBytesResumable(storageRef, file); line shows a message
Argument type StorageReference is not assignable to parameter type types.Reference"
What is wrong with my code?

Related

Uncaught (in promise) FirebaseError: Firebase Storage: Object 'john' does not exist. (storage/object-not-found)

I am using ReactJS in my SimpChat Application to upload data from my Register Form to the Firestore Database and I got an error that the Uncaught (in promise) FirebaseError: Firebase Storage: Object 'john' does not exist. (storage/object-not-found). Where did I got an error and how can I solve it?
Here is my Register Form code:
import React from 'react'
import { useState } from 'react';
import Add from "../img/addAvatar.png"
import { createUserWithEmailAndPassword, updateProfile } from "firebase/auth";
import { auth, storage } from "../firebase";
import { ref, uploadBytesResumable, getDownloadURL } from "firebase/storage";
import { doc, setDoc } from "firebase/firestore";
import { db } from "../firebase";
const Register = () => {
const [err,setErr] = useState(false);
const handleSubmit = async (e) => {
e.preventDefault()
// console.log(e.target[0].value)
const displayName = e.target[0].value;
const email = e.target[1].value;
const password = e.target[2].value;
const file = e.target[3].files[0];
try {
const res = await createUserWithEmailAndPassword(auth, email, password)
const storageRef = ref(storage, displayName);
const uploadTask = uploadBytesResumable(storageRef, file);
// Register three observer
uploadTask.on(
(error) => {
setErr(true);
},
() => {
getDownloadURL(uploadTask.snapshot.ref).then(async (downloadURL) => {
await updateProfile (res.user, {
displayName,
photoURL: downloadURL,
});
await setDoc(doc(db, "users", res.user.uid), {
uid: res.user.uid,
displayName,
email,
photoURL: downloadURL,
});
});
}
);
} catch (err) {
setErr(true);
}
}
return (
<div className='formContainer'>
<div className='formWrapper'>
<span className="logo">SimpChat</span>
<span className="logo">Register</span>
<form onSubmit={handleSubmit}>
<input type="text" placeholder='display name'/>
<input type="email" placeholder='email' />
<input type="password" placeholder='password' />
<input style={{ display: "none" }} type="file" id='file' />
<label htmlFor="file">
<img src={Add} alt="" />
<span>Add an avatar</span>
</label>
<button>Sign up</button>
{err && <span>Something went wrong</span>}
</form>
<p>You do have an account? Login</p>
</div>
</div>
)
}
export default Register
The first parameter in uploadTask.on() should be the event i.e. state_changed. Try:
// Ensure that all values are defined
console.log(file, displayName);
const storageRef = ref(storage, displayName);
const uploadTask = uploadBytesResumable(storageRef, file);
uploadTask.on(
'state_changed',
(error) => {
console.log('Error upload file', error)
setErr(true);
},
() => {
getDownloadURL(uploadTask.snapshot.ref).then(async (downloadURL) => {
console.log({ downloadURL })
});
}
);

xhr.js:220 POST http://localhost:3000/EShop/register 400 (Bad Request)

Trying to POST request to send data to database but it always shows 400 bad request.
The AuthReducer file is as follow. Data is not getting posted when done in Frontend but its properly working when tested in postman api.
export const Register = (username, email , password) => async(disptach) => {
try{
disptach({type:REGISTER_USER_REQUEST})
const config = {
Headers:{
'Content-Type':'application/json'
}
}
const { data } = await axios.post('/EShop/register', {username ,email , password} , config)
disptach({
type:REGISTER_USER_SUCCESS,
payload:data.user
})
}catch(error){
disptach({
type:REGISTER_USER_FAIL,
payload : error.response.data.message
})
}
}
The register form is as follow..
import React, { useState, useEffect } from "react";
import { Link, useNavigate } from "react-router-dom"
import { useSelector, useDispatch } from "react-redux"
import Loader from "./loader";
import { Register } from "../actions/UserAction";
import "../css-files/Account.css"
export default function register() {
const [email, setemail] = useState('');
const [password, setpassword] = useState('');
const [username, setusername] = useState('');
const disptach = useDispatch();
const navigate = useNavigate();
const { isAuthenticated, error, loading } = useSelector(state => state.user)
useEffect(() => {
if (isAuthenticated) {
navigate('/account/login')
}
}, [disptach, isAuthenticated])
const SubmitRegisterHandler = (e) => {
e.preventDefault()
disptach(Register(username, email, password))
}
return (
<div id="Account_container">
{loading ?
<Loader />
:
<div id="wrapper">
<div id="Wrap_First">
<img src="https://res.cloudinary.com/dqxozrie1/image/upload/v1659935744/eshop/online-registration-sign-up_gfb2gs.webp" />
</div>
<div id="Wrap_Second">
<div id="login">
<h2>Create New Account</h2>
<form onSubmit={SubmitRegisterHandler}>
<input
required
type="text"
placeholder="Username"
value={username}
onChange={(e) => { setusername(e.target.value) }}
/>
<input
required
type="email"
placeholder="Email"
value={email}
onChange={(e) => { setemail(e.target.value) }}
/>
<input
required
type="password"
placeholder="Password"
value={password}
onChange={(e) => { setpassword(e.target.value) }}
/>
<button>Register</button>
</form>
<p id="existing_acc"><Link to="/account/login">Already have an account !</Link></p>
</div>
</div>
</div>
}
</div>
);
}
It gives 400 bad request always. Please help me how to resolve this issue.

Difficulty With Register Route, not able to register without image

In the User model I have set avatar to be not required
avatar: {
public_id: {
type: String,
},
url: {
type: String,
},
},
but still if I register without image it shows error POST http://localhost:3000/api/v1/register 500 (Internal Server Error) and REGISTER_USER_FAIL constant state is returned
Here is my UserController.jsx, Register Route
exports.registerUser = catchAsyncErrors(async (req, res, next) => {
const myCloud = await cloudinary.v2.uploader.upload(req.body.avatar, {
folder: "avatars",
width: 150,
crop: "scale",
});
const { name, email, password } = req.body;
if(req.body.avatar){
const user = await User.create({
name,
email,
password,
avatar: {
public_id: myCloud.public_id,
url: myCloud.secure_url,
},
});
sendToken(user, 201, res);
} else {
const user = await User.create({
name,
email,
password
});
sendToken(user, 201, res);
}
});
SignUp Component
import React, {Fragment,useRef,useState, useEffect} from "react";
import "./LoginSignUp.css";
import Loader from "../layout/Loader/Loader";
import { Link, useNavigate } from "react-router-dom";
import LockOpenIcon from '#mui/icons-material/LockOpen';
import EmailIcon from '#mui/icons-material/Email';
import PersonIcon from '#mui/icons-material/Person';
import img from "../../images/Profile.png";
import {useSelector, useDispatch} from "react-redux";
import {clearErrors, login , register} from "../../actions/userAction.jsx";
import {useAlert} from "react-alert";
export default function LoginSignUp() {
const dispatch = useDispatch();
const alert = useAlert();
const navigate = useNavigate();
const { error, loading, isAuthenticated } = useSelector(
(state) => state.user
);
const loginTab = useRef(null);
const registerTab = useRef(null);
const switcherTab = useRef(null);
const [loginEmail, setLoginEmail] = useState("");
const [loginPassword, setLoginPassword] = useState("");
const [user, setUser] = useState({
name: "",
email: "",
password: "",
});
const { name, email, password } = user;
const [avatar, setAvatar] = useState(img);
const [avatarPreview, setAvatarPreview] = useState(img);
const loginSubmit = (e) => {
e.preventDefault();
dispatch(login(loginEmail, loginPassword));
};
const registerSubmit = (e) => {
e.preventDefault();
const myForm = new FormData();
myForm.set("name", name);
myForm.set("email", email);
myForm.set("password", password);
if(avatar!==img){
myForm.set("avatar", avatar);
}
dispatch(register(myForm));
};
const registerDataChange = (e) => {
if (e.target.name === "avatar") {
const reader = new FileReader();
reader.onload = () => {
if (reader.readyState === 2) {
setAvatarPreview(reader.result);
setAvatar(reader.result);
}
};
if(reader){
reader.readAsDataURL(e.target.files[0]);
}
} else {
setUser({ ...user, [e.target.name]: e.target.value });
}
}
useEffect(() => {
if (error) {
alert.error(error);
dispatch(clearErrors());
}
if (isAuthenticated) {
navigate("/");
}
}, [dispatch, error, alert, navigate, isAuthenticated]);
const switchTabs = (e, tab) => {
if (tab === "login") {
switcherTab.current.classList.add("shiftToNeutral");
switcherTab.current.classList.remove("shiftToRight");
registerTab.current.classList.remove("shiftToNeutralForm");
loginTab.current.classList.remove("shiftToLeft");
}
if (tab === "register") {
switcherTab.current.classList.add("shiftToRight");
switcherTab.current.classList.remove("shiftToNeutral");
registerTab.current.classList.add("shiftToNeutralForm");
loginTab.current.classList.add("shiftToLeft");
}
};
return (
<Fragment>
{loading ? (
<Loader />
) : (
<Fragment>
<div className="LoginSignUpContainer">
<div className="LoginSignUpBox">
<div>
<div className="login_signUp_toggle">
<p onClick={(e) => switchTabs(e, "login")}>LOGIN</p>
<p onClick={(e) => switchTabs(e, "register")}>REGISTER</p>
</div>
<button ref={switcherTab}></button>
</div>
<form className="loginForm" ref={loginTab} onSubmit={loginSubmit}>
<div className="loginEmail">
<EmailIcon />
<input
type="email"
placeholder="Email"
required
value={loginEmail}
onChange={(e) => setLoginEmail(e.target.value)}
/>
</div>
<div className="loginPassword">
<LockOpenIcon />
<input
type="password"
placeholder="Password"
required
value={loginPassword}
onChange={(e) => setLoginPassword(e.target.value)}
/>
</div>
<Link to="/password/forgot">Forget Password ?</Link>
<input type="submit" value="Login" className="loginBtn" />
</form>
<form
className="signUpForm"
ref={registerTab}
encType="multipart/form-data"
onSubmit={registerSubmit}
>
<div className="signUpName">
<PersonIcon />
<input
type="text"
placeholder="Name"
required
name="name"
value={name}
onChange={registerDataChange}
/>
</div>
<div className="signUpEmail">
<EmailIcon />
<input
type="email"
placeholder="Email"
required
name="email"
value={email}
onChange={registerDataChange}
/>
</div>
<div className="signUpPassword">
<LockOpenIcon />
<input
type="password"
placeholder="Password"
required
name="password"
value={password}
onChange={registerDataChange}
/>
</div>
<div id="registerImage">
<img src={avatarPreview} alt="Avatar Preview" />
<input
type="file"
name="avatar"
accept="image/*"
onChange={registerDataChange}
/>
<span>*image size less than 500KB</span>
</div>
<input type="submit" value="Register" className="signUpBtn" />
</form>
</div>
</div>
</Fragment>
)}
</Fragment>
);
};
Register route works fine only if I use image while registering.
When registering without image
// v-- seems you are using avatar before checking if it's in the body
const myCloud = await cloudinary.v2.uploader.upload(req.body.avatar, {
folder: "avatars",
width: 150,
crop: "scale",
});
const { name, email, password } = req.body;
if(req.body.avatar){

POST http://localhost:3000/api/v1/register 500 (Internal Server Error)

When Cloudinary is not included my Code runs fine on Postman. As I include Cloudinary to in register route to add photos to account, I am getting this error
userAction.jsx
export const register = (userData) => async (dispatch) => {
try {
dispatch({ type: REGISTER_USER_REQUEST });
const config = { headers: { "Content-Type": "multipart/form-data" } };
const { data } = await axios.post(`/api/v1/register`, userData, config);
dispatch({ type: REGISTER_USER_SUCCESS, payload: data.user });
} catch (error) {
dispatch({
type: REGISTER_USER_FAIL,
payload: error.response.data.message,
});
}
};
LoginSignup.jsx
import React, {Fragment,useRef,useState, useEffect} from "react";
import "./LoginSignUp.css";
import Loader from "../layout/Loader/Loader";
import { Link, useNavigate } from "react-router-dom";
import LockOpenIcon from '#mui/icons-material/LockOpen';
import EmailIcon from '#mui/icons-material/Email';
import PersonIcon from '#mui/icons-material/Person';
import img from "../../images/Profile.png";
import {useSelector, useDispatch} from "react-redux";
import {clearErrors, login , register} from "../../actions/userAction.jsx";
import {useAlert} from "react-alert";
export default function LoginSignUp(){
const dispatch = useDispatch();
const alert = useAlert();
const navigate = useNavigate();
const {error,loading,isAuthenticated} = useSelector((state)=>state.user);
const loginTab=useRef(null);
const registerTab = useRef(null);
const switcherTab = useRef(null);
const [loginEmail,setLoginEmail] = useState("");
const [loginPassword,setLoginPassword] = useState("");
const [user,setUser] = useState({
name:"",
email:"",
password:"",
});
const {name,email,password} = user;
const [avatar, setAvatar] = useState(img);
const [avatarPreview, setAvatarPreview] = useState(img);
function loginSubmit(e){
e.preventDefault();
dispatch((login(loginEmail,loginPassword)));
}
function registerSubmit(e){
e.preventDefault();
const myForm = new FormData();
myForm.set("name",name);
myForm.set("email",email);
myForm.set("password",password);
myForm.set("avatar",avatar);
dispatch(register(myForm));
}
function registerDataChange(e){
if(e.target.name==="avatar"){
const reader = new FileReader();
reader.onload = ()=>{
if(reader.readyState===2){
setAvatarPreview(reader.result);
setAvatar(reader.result);
}
};
reader.readAsDataURL(e.target.files[0]);
} else {
setUser({...user, [e.target.name]:e.target.value});
}
}
useEffect(()=>{
if(error){
alert.error(error);
dispatch(clearErrors());
}
if(isAuthenticated){
navigate(`/account`);
}
},[dispatch,error,alert,isAuthenticated,navigate]);
const switchTabs = (e, tab) => {
if (tab === "login") {
switcherTab.current.classList.add("shiftToNeutral");
switcherTab.current.classList.remove("shiftToRight");
registerTab.current.classList.remove("shiftToNeutralForm");
loginTab.current.classList.remove("shiftToLeft");
}
if (tab === "register") {
switcherTab.current.classList.add("shiftToRight");
switcherTab.current.classList.remove("shiftToNeutral");
registerTab.current.classList.add("shiftToNeutralForm");
loginTab.current.classList.add("shiftToLeft");
}
};
return(
<Fragment>
{loading ? <Loader/> : (
<Fragment>
<div className="LoginSignUpContainer">
<div className="LoginSignUpBox">
<div>
<div className="login_signUp_toggle">
<p onClick={(e)=>switchTabs(e,"login")}>Login</p>
<p onClick={(e)=>switchTabs(e,"register")}>Register</p>
</div>
<button ref={switcherTab}></button>
</div>
<form
className="signUpForm"
ref={registerTab}
encType="multipart/form-data"
onSubmit={registerSubmit}
>
<div className="signUpName">
<PersonIcon />
<input
type="text"
placeholder="Name"
required
name="name"
value={name}
onChange={registerDataChange}
/>
</div>
<div className="signUpEmail">
<EmailIcon />
<input
type="email"
placeholder="Email"
required
name="email"
value={email}
onChange={registerDataChange}
/>
</div>
<div className="signUpPassword">
<LockOpenIcon />
<input
type="password"
placeholder="Password"
required
name="password"
value={password}
onChange={registerDataChange}
/>
</div>
<div id="registerImage">
<img src={avatarPreview} alt="Avatar Preview" />
<input
type="file"
name="avatar"
accept="image/*"
onChange={registerDataChange}
/>
</div>
<input type="submit" value="Register" className="signUpBtn" />
</form>
</div>
</div>
</Fragment>
)}
</Fragment>
);
}
userController.jsx
exports.RegisterUser = catchAsyncErrors( async (req,res,next)=>{
// const myCloud = await cloudinary.v2.uploader.upload(req.body.avatar,{
// folder: "avatars",
// width: 150,
// crop:"scale",
// });
const {name,email,password} = req.body;
const user = await User.create({
name,
email,
password,
avatar: {
public_id:"myCloud.public_id",
url: "myCloud.secure_url",
}
});
sendToken(user,201,res);
});
I have an id on Cloudinary and imported its Name, API_KEY, API_SECRET
Backend code works well on postman without Cloudinary
In Postman you are not adding image. But in client side login form, you are adding image alongside other data.
In backend you are getting email, name, password from req.body.But image data will be available in req.file.
As an example
if (req.file) {
const avatar= req.file.originalName;
req.body = { ...req.body, avatar};
}
await Model.create(req.body);

react js and node Can't see img of new user

When I try to register a new user all data are passed except "avatar", even if that avatar is regularly uploaded on my Cloudinary.
Don't even know what is the problem in and tried to find answer on google but unsuccessfully, so any help is very welcome :D
Here is some code, if need more tell me in a comment and I'll send you
Cannot finish my site, don't know what to do...
// frontend Register component
import React, { Fragment, useState, useEffect } from 'react';
import { useNavigate } from 'react-router-dom';
import MetaData from '../layout/MetaData';
import { useAlert } from 'react-alert';
import { useDispatch, useSelector } from 'react-redux';
import { register, clearErrors } from '../../actions/userActions';
const Register = () => {
const navigate = useNavigate();
const [user, setUser] = useState({
name: '',
email: '',
password: '',
});
const { name, email, password } = user;
const [avatar, setAvatar] = useState('');
const [avatarPreview, setAvatarPreview] = useState(
'/images/default_avatar.jpg'
);
const alert = useAlert();
const dispatch = useDispatch();
const { isAuthenticated, error, loading } = useSelector(
(state) => state.auth
);
useEffect(() => {
if (isAuthenticated) {
navigate('/');
}
if (error) {
alert.error(error);
dispatch(clearErrors());
}
}, [dispatch, alert, isAuthenticated, error, navigate]);
const submitHandler = (e) => {
e.preventDefault();
const formData = new FormData();
formData.set('name', name);
formData.set('email', email);
formData.set('password', password);
formData.set('avatar', avatar);
dispatch(register(formData));
};
const onChange = (e) => {
if (e.target.name === 'avatar') {
const reader = new FileReader();
reader.onload = () => {
if (reader.readyState === 2) {
setAvatarPreview(reader.result);
setAvatar(reader.result);
}
};
reader.readAsDataURL(e.target.files[0]);
} else {
setUser({ ...user, [e.target.name]: e.target.value });
}
};
return (
<Fragment>
<MetaData title={'Register User'} />
<div className='row wrapper'>
<div className='col-10 col-lg-5'>
<form
className='shadow-lg'
onSubmit={submitHandler}
encType='multipart/form-data'
>
<h1 className='mb-3'>Register</h1>
<div className='form-group'>
<label htmlFor='email_field'>Name</label>
<input
type='name'
id='name_field'
className='form-control'
name='name'
value={name}
onChange={onChange}
/>
</div>
<div className='form-group'>
<label htmlFor='email_field'>Email</label>
<input
type='email'
id='email_field'
className='form-control'
name='email'
value={email}
onChange={onChange}
/>
</div>
<div className='form-group'>
<label htmlFor='password_field'>Password</label>
<input
type='password'
id='password_field'
className='form-control'
name='password'
value={password}
onChange={onChange}
/>
</div>
<div className='form-group'>
<label htmlFor='avatar_upload'>Avatar</label>
<div className='d-flex align-items-center'>
<div>
<figure className='avatar mr-3 item-rtl'>
<img
src={avatarPreview}
className='rounded-circle'
alt='Avatar Preview'
/>
</figure>
</div>
<div className='custom-file'>
<input
type='file'
name='avatar'
className='custom-file-input'
id='customFile'
accept='iamges/*'
onChange={onChange}
/>
<label className='custom-file-label' htmlFor='customFile'>
Choose Avatar
</label>
</div>
</div>
</div>
<button
id='register_button'
type='submit'
className='btn btn-block py-3'
disabled={loading ? true : false}
>
REGISTER
</button>
</form>
</div>
</div>
</Fragment>
);
};
export default Register;
// backend Register a user => /api/v1/register
exports.registerUser = catchAsyncErrors(async (req, res, next) => {
const result = await cloudinary.v2.uploader.upload(req.body.avatar, {
folder: 'avatars',
width: 150,
crop: 'scale',
});
const { name, email, password } = req.body;
const user = await User.create({
name,
email,
password,
avatar: {
public_id: result.public_id,
url: result.secure_url,
},
});
sendToken(user, 200, res);
});

Categories