Black screen in react code - possible firebase auth issue - reactjs

this code is giving me a blank screen i have no idea as to why i would assume its firebase auth or the logic giving me trouble im running this in vscode and its compiling sucessfully
import { createUserWithEmailAndPassword } from "firebase/auth";
import React, { useState } from "react";
import { auth } from "../firebase";
import { Link } from "react-router-dom";
const SignUp = () => {
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const [name, setName] = useState("");
const [error, setError] = useState("");
const signUp = (e) => {
e.preventDefault();
auth.createUserWithEmailAndPassword(email, password).then((userCredential) => {
userCredential.user
.updateProfile({
displayName: name,
})
.then(() => {
console.log("user name added");
})
.catch((error) => {
console.log(error);
});
})
.catch((error) => {
setError(error.message);
});
};
return (
<div className="container mx-auto flex justify-center pt-6">
<form className="bg-white p-6 rounded-lg shadow-xl" onSubmit={signUp}>
<div className="mb-4">
<label
className="block text-gray-700 font-medium mb-2"
htmlFor="name"
>
Name
</label>
<input
className="w-full border border-gray-400 p-2 rounded-md"
id="name"
type="text"
placeholder="Enter your name"
onChange={(e) => setName(e.target.value)}
/>
</div>
<div className="mb-4">
<label
className="block text-gray-700 font-medium mb-2"
htmlFor="email"
>
Email
</label>
<input
className="w-full border border-gray-400 p-2 rounded-md"
id="email"
type="email"
placeholder="Enter your email"
onChange={(e) => setEmail(e.target.value)}
/>
</div>
<div className="mb-4">
<label
className="block text-gray-700 font-medium mb-2"
htmlFor="password"
>
Password
</label>
<input
className="w-full border border-gray-400 p-2 rounded-md"
id="password"
type="password"
placeholder="Enter your password"
onChange={(e) => setPassword(e.target.value)}
/>
</div>
<div className="text-red-500 text-xs mb-4">{error}</div>
<button
className="bg-indigo-500 hover:bg-indigo-600 text-white py-2 px-4
rounded-md"
type="submit"
>
Sign Up
</button>
<Link
to="/login"
className="text-indigo-500 hover:text-indigo-600 font-medium py-2 px-4"
>
Already have an account?
</Link>
</form>
</div>
);
};
export default SignUp;
was trying to make a signup page for my website that took in email and password to authenticate but also took a name to display on profile

Related

React TS, First submit returns empty array

I'm trying to make simple form using React,Typescript, have done some inputs and while adding them with onChange to one main state, first submit always returns empty. Why?
import React from "react";
import { useState } from "react";
import { Form } from "../components/Form/Form";
import { Navbar } from "../components/Navbar";
export const MainPage = () => {
const [formData, setFormData] = useState([]);
return (
<div className="w-full flex">
<Navbar />
<Form formData={formData} setFormData={setFormData} />
</div>
);
};
import React from "react";
import { useState } from "react";
interface Props{
formData: string[];
setFormData: React.Dispatch<React.SetStateAction<any>>;
}
export const Form: React.FC<Props> = ({setFormData, formData}) => {
const [organization, setOrganization] = useState<string>("");
const [title, setTitle] = useState<string>("");
const [firstName, setFirstName] = useState<string>("");
const [lastName, setLastName] = useState<string>("");
const [languages, setLanguages] = useState<string>("");
const [employmentType, setEmploymentType] = useState<string>("");
const [profession, setProfession] = useState<string>("");
const [proficiency, setProficiency] = useState<string>("");
const submitData = (e: any) => {
const data = {
organization,
title,
firstName,
lastName,
languages,
employmentType,
profession,
proficiency,
};
setFormData((prevData: any) => [...prevData, data]);
console.log(formData)
}
return (
<div className="w-full">
<div className="w-3/4 mx-auto mt-5">
<h1 className="text-2xl">About you</h1>
<div className="top flex mt-16 gap-8">
<div>
<h2 className="text-xl font-bold">Personal info</h2>
<p className="text-sm font-extralight">
Provide your personal info
</p>
</div>
<div className="flex flex-col gap-5">
<div>
<input
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
setOrganization(e.target.value);
}}
className="w-full bg-gray-200 p-2 rounded-md placeholder:text-sm placeholder:text-black"
placeholder="Organization"
></input>
</div>
<div className="flex gap-3">
<select
onChange={(e: React.ChangeEvent<HTMLSelectElement>) => {
setTitle(e.target.value);
}}
className="bg-gray-200 p-2 rounded-md placeholder:text-sm placeholder:text-black"
>
<option value="Title">Title</option>
<option value="Mr">Mr</option>
<option value="Mrs">Mrs</option>
<option value="Miss">Miss</option>
<option value="Ms">Ms</option>
</select>
<input
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
setFirstName(e.target.value);
}}
className="bg-gray-200 p-2 rounded-md placeholder:text-sm placeholder:text-black"
placeholder="First name"
></input>
<input
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
setLastName(e.target.value);
}}
className="bg-gray-200 p-2 rounded-md placeholder:text-sm placeholder:text-black"
placeholder="Last name"
></input>
</div>
</div>
</div>
</div>
<hr className="mt-16"></hr>
<div className="bottom w-3/4 mx-auto mt-16">
<div>
<h2 className="text-xl font-bold">Professional info</h2>
<p className="text-sm font-extralight">
Provide your professional info
</p>
</div>
<div className="mt-14">
<div className="flex flex-col gap-8 items-center">
<input
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
setLanguages(e.target.value);
}}
className="w-3/4 bg-gray-200 p-2 rounded-md placeholder:text-sm placeholder:text-black"
placeholder="Language(s) separate with comma"
></input>
<input
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
setEmploymentType(e.target.value);
}}
className="w-3/4 bg-gray-200 p-2 rounded-md placeholder:text-sm placeholder:text-black"
placeholder="Type of employment"
></input>
<input
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
setProfession(e.target.value);
}}
className="w-3/4 bg-gray-200 p-2 rounded-md placeholder:text-sm placeholder:text-black"
placeholder="Profession"
></input>
<input
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
setProficiency(e.target.value);
}}
className="w-3/4 bg-gray-200 p-2 rounded-md placeholder:text-sm placeholder:text-black"
placeholder="Proficiency level"
></input>
</div>
</div>
</div>
<div className="w-3/4 flex justify-end mt-7">
<button onClick={(e) => submitData(e)} className="bg-sky-800 p-2 text-white rounded-md">Submit</button>
</div>
</div>
);
};
Read other threads about similar issue but there was mentioned using async, i believe there would be another way to fix this. Thank you
Hi there setState in Reactjs is asynchronous so when you called submitData console.log(formData) gets triggered even before the setState completed its task and with asynchronous code, javascript does not have to wait for setState to finish up it just keeps running other tasks.
setFormData((prevData: anyType) => {
const newData = [...prevData, data];
console.log(newData);
return newData;
});

Login button doesn't take effect when clicked

I am a total beginner in react and I have set up a an authentication system in my react webapp which is connected to a mongodb database.
I can successfully register but I can't login with the user details which have been registered - means, that nothing happens when I click the Login button.
RequireAuth.jsx:
import { Navigate } from "react-router-dom";
import { useAuth } from './auth';
function getToken() {
return localStorage.getItem('token');
}
function getInternalData() {
return JSON.parse(localStorage.getItem('internalData'));
}
export const RequireAuth = ({ children }) => {
const auth = useAuth();
if (!getToken()) {
return <Navigate to="/login" />;
}
return children;
};
export const RequireLogOut = ({ children }) => {
const auth = useAuth();
if (getToken()) {
return <Navigate to="/home" />;
}
return children;
};
export { getToken, getInternalData };
auth.jsx:
import {useState, useContext, createContext } from "react";
const AuthContext = createContext(null);
export const AuthProvider = ({children }) => {
const [token, setToken] = useState("");
const login = (token, internalData) => {
console.log(token);
localStorage.setItem('token', JSON.stringify(token));
localStorage.setItem('internalData', JSON.stringify(internalData));
setToken(token);
};
const logout = () => {
localStorage.removeItem('token');
localStorage.removeItem('internalData');
setToken("");
}
return <AuthContext.Provider value={{token, login, logout}}>{children}</AuthContext.Provider>
};
export const useAuth = () => {
return useContext(AuthContext);
};
login.jsx:
import { useState } from 'react';
import { useNavigate, Link } from 'react-router-dom'
import { useAuth } from './auth';
import axios from 'axios'
import { LockClosedIcon } from '#heroicons/react/24/solid'
import { RequireAuth, RequireLogOut } from "./RequireAuth";
async function loginUser(credentials) {
return fetch('http://localhost:4000/login', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(credentials)
})
.then(data => data.json())
}
export default function LoginForm() {
const [loginValues, setLoginValues] = useState({ email: "", password: "" });
const navigate = useNavigate()
const [error, setError] = useState("");
const auth = useAuth();
const handleChange = (e) => {
const { name, value } = e.target;
const newValues = { ...loginValues, [name]: value };
console.log(newValues);
setLoginValues(newValues);
};
const handleSubmit = async e => {
e.preventDefault();
//const token = await loginUser(loginValues);
const tokenData = await axios.post('http://localhost:4000/login/', loginValues);
console.log(tokenData.data)
if (tokenData.data.success) {
setError("");
auth.login(tokenData.data.token, tokenData.data.internalData);
}
else {
setError("Credentials are incorrect. Try again");
}
}
return (
<>
<div className="min-h-full flex items-center justify-center py-12 px-4 sm:px-6 lg:px-8">
<div className="max-w-md w-full space-y-8">
<div>
<img
className="mx-auto h-36 w-auto"
src="/images/logo.png"
alt="Workflow"
/>
<h2 className="mt-6 text-center text-3xl tracking-tight font-bold text-gray-900">
Sign in to your account
</h2>
<p className="mt-2 text-center text-sm text-gray-600">
Or{' '}
<a href="http://localhost:3000/register" className="font-medium text-gameblue hover:text-gamebluehover">
don't have an account yet?
</a>
</p>
</div>
{error ? <div>{error}</div> : ""}
<form onSubmit={handleSubmit} className="mt-8 space-y-6" action="#" method="POST">
<input type="hidden" name="remember" defaultValue="true" />
<div className="rounded-md shadow-sm -space-y-px">
<div>
<label htmlFor="email-address" className="sr-only">
Email address
</label>
<input
onChange={handleChange}
value={loginValues.email}
id="email-address"
name="email"
type="email"
autoComplete="email"
required
className="appearance-none rounded-none relative block w-full px-3 py-2 border border-gray-300 placeholder-gray-500 text-gray-900 rounded-t-md focus:outline-none focus:ring-indigo-500 focus:border-gameblue focus:z-10 sm:text-sm"
placeholder="Email address"
/>
</div>
<div>
<label htmlFor="password" className="sr-only">
Password
</label>
<input
onChange={handleChange}
value={loginValues.password}
id="password"
name="password"
type="password"
autoComplete="current-password"
required
className="appearance-none rounded-none relative block w-full px-3 py-2 border border-gray-300 placeholder-gray-500 text-gray-900 rounded-b-md focus:outline-none focus:ring-indigo-500 focus:border-gameblue focus:z-10 sm:text-sm"
placeholder="Password"
/>
</div>
</div>
<div className="flex items-center justify-between">
<div className="flex items-center">
<input
id="remember-me"
name="remember-me"
type="checkbox"
className="h-4 w-4 text-indigo-600 focus:ring-indigo-500 border-gray-300 rounded"
/>
<label htmlFor="remember-me" className="ml-2 block text-sm text-gray-900">
Remember me
</label>
</div>
<div className="text-sm">
<a href="#" className="font-medium text-gameblue hover:text-gamebluehover">
Forgot your password?
</a>
</div>
</div>
<div>
<button
type="submit"
className="group relative w-full flex justify-center py-2 px-4 border border-transparent text-sm font-medium rounded-md text-white bg-gameblue hover:bg-gamebluehover focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
>
<span className="absolute left-0 inset-y-0 flex items-center pl-3">
<LockClosedIcon className="h-5 w-5 text-gamebluelight group-hover:text-gamebluelightest" aria-hidden="true" />
</span>
Sign in
</button>
</div>
</form>
</div>
</div>
</>
);
}

Import password filed as an functional component in ReactJs

I want to store this react hook and password field in a separate js file and I want to import it to my register form how can I do that?
Password Field
<label class="font-medium block mb-1 mt-6 text-gray-700" for="password">
Password
</label>
<div class="relative w-full">
<div class="absolute inset-y-0 right-0 flex items-center px-2">
<input class="hidden js-password-toggle" id="toggle" type="checkbox" />
<label class="bg-gray-300 hover:bg-gray-400 rounded px-2 py-1 text-sm text-gray-600 font-mono cursor-pointer js-password-label" for="toggle">show</label>
</div>
<input class="appearance-none border-2 rounded w-full py-3 px-3 leading-tight border-gray-300 bg-gray-100 focus:outline-none focus:border-indigo-700 focus:bg-white text-gray-700 pr-16 font-mono js-password" id="password" type="password" autocomplete="off"
/>
</div>
Password function filed
useEffect(() => {
const passwordToggle = document.querySelector('.js-password-toggle')
passwordToggle.addEventListener('change', function() {
const password = document.querySelector('.js-password'),
passwordLabel = document.querySelector('.js-password-label')
if (password.type === 'password') {
password.type = 'text'
passwordLabel.innerHTML = 'hide'
} else {
password.type = 'password'
passwordLabel.innerHTML = 'show'
}
password.focus()
})
}, [])
Form That I want to add this password filed
import React, { useEffect, useState } from "react";
import Buttons from "../../../elements/form/Button";
import PasswordInput from "../../../elements/form/PasswordInput";
import { Col, Input, Row, Select, Form, InputNumber, Divider } from "antd";
import { ChangePassword, sentOtp, changePhoneNumber, requestOtp } from "./SecurityApi";
const { Option } = Select;
const Security = () => {
const [phoneNo, setPhoneNo] = useState("");
const [otp, setOtp] = useState("");
//const [password, setPassword] = useState("");
const [conPassword, setConPassword] = useState("");
const [passError, setPassError] = useState();
const [otpError, setOtpError] = useState();
const [user, setUser] = useState(null);
//changing password
const [editPasswordState, setEditPasswordState] = useState(false);
const [password, setPassword] = useState({
password: "",
});
const handlePasswordChange = async () => {
if (password === user.password) {
return;
}
if (password.trim() === "") {
console.log("cant be empty");
return;
}
await ChangePassword(password, setUser);
};
useEffect(() => {
setPassError(password && conPassword && password !== conPassword);
}, [password, conPassword]);
useEffect(() => {
setOtpError(!otp && phoneNo);
}, [otp]);
//onSubmit password
const onSubmit = async () => {
if (passError) return false;
try {
const res = await ChangePassword({ password });
setPassword("");
setConPassword("");
alert("Password Changed !!");
} catch (error) {
alert("Something went wrong !!");
}
};
//OTP
const sendOtp = async () => {
if (phoneNo === "") return false;
try {
const res = await sentOtp(phoneNo);
alert(`Otp is ${res} !!`);
} catch (error) {
alert("Something went wrong !!");
}
};
//Changing the phone number
const changePhoneNo = async () => {
if (phoneNumber === "") return false;
if (otp === "") {
setOtpError(true);
return false;
}
try {
const res = await changePhoneNumber(phoneNo);
setPhoneNumber("");
setOtp("");
alert("Phone Number Changed !!");
} catch (error) {
alert("Something went wrong !!");
}
};
const [editPhoneNumberState, setEditPhoneNumberState] = useState(false);
const [phoneNumber, setPhoneNumber] = useState({
password: "",
});
const handlePhoneNumberChange = async () => {
if (phoneNumber === user.phoneNumber) {
return;
}
if (password.trim() === "") {
console.log("cant be empty");
return;
}
await ChangePassword(password, setUser);
};
return (
<>
<div className="md:pl-8 sm:pl-0 ">
{/* ---------- Password Change ------------ */}
<div class="mt-10 sm:mt-0">
<div class="md:grid md:grid-cols-3 md:gap-6">
<div class="md:col-span-1">
<div class="px-4 sm:px-0">
<h3 class="text-lg font-medium leading-6 text-gray-900">
Change Password
</h3>
<p class="mt-1 text-sm text-gray-600">Change password here</p>
</div>
</div>
<div class="mt-5 md:mt-0 md:col-span-2">
<form action="#" method="POST">
<div class="shadow overflow-hidden sm:rounded-md">
<div class="px-4 py-3 bg-gray-50 text-right sm:px-6">
<div class="grid grid-cols-6 gap-6">
<div class="col-span-6 sm:col-span-3">
<Buttons
title={
!editPasswordState ? "Edit Full Password" : "Cancel"
}
outline
onClick={() => {
setEditPasswordState(!editPasswordState);
}}
class="inline-flex
justify-center
py-2 px-4 border
border-transparent
shadow-sm text-sm
font-medium rounded-md
text-white bg-red-400
hover:bg-red-400
focus:outline-none f
ocus:ring-2
focus:ring-offset-2
focus:ring-red-500"
/>
</div>
<div class="col-span-6 sm:col-span-3">
{editPasswordState && (
<Buttons
title="Save"
onClick={async () => {
setEditPasswordState(false);
await handlePasswordChange();
}}
/>
)}
</div>
</div>
</div>
<div class="px-4 py-5 bg-white sm:p-6">
{/* OTP Check*/}
<div class="grid grid-cols-6 gap-1">
<div class="col-span-4 sm:col-span-3">
<label
for="first-name"
class="block text-sm font-medium text-gray-700"
>
Send OTP
</label>
<Buttons
title={"Request OTP"}
outline
onClick={async () => {
await requestOtp(user.phoneNumber);
}}
/>
</div>
<div class="col-span-6 sm:col-span-3">
<label
for="last-name"
class="block text-sm font-medium text-gray-700"
>
Enter OTP
</label>
<input
type="text"
name="last-name"
id="last-name"
autocomplete="family-name"
class="mt-1
focus:ring-red-400
focus:border-red-400
block w-full
shadow-sm sm:text-sm
border-gray-300 rounded-md"
/>
{passError && (
<Col className="text-red-500">
OTP doesn't Correct !!
</Col>
)}
</div>
</div>
{/* OTP Check End */}
</div>
<div class="px-4 py-5 bg-white sm:p-6">
{/* Password Check*/}
<div class="grid grid-cols-6 gap-6">
<div class="col-span-6 sm:col-span-3">
<label
for="first-name"
class="block text-sm font-medium text-gray-700"
>
New Password
</label>
<Input.Password
value={password}
onChange={(event) => {
setPassword(event.target.value);
}}
class="mt-1
focus:ring-red-400
focus:border-red-400
block w-full
shadow-sm sm:text-sm
border-gray-300 rounded-md"/>
This is the Place
</div>
<div class="col-span-6 sm:col-span-3">
<label
for="last-name"
class="block text-sm font-medium text-gray-700"
>
Confirm New Password
</label>
<Input.Password
value={conPassword}
onChange={(event) => {
setConPassword(event.target.value);
}}
/>
{passError && (
<Col className="text-red-500">
Password doesn't match !!
</Col>
)}
</div>
</div>
{/* Password Check End*/}
</div>
</div>
</form>
</div>
</div>
</div>
{/* ------- End Password Change -------- */}
<div class="px-4 py-1 bg-black-50 text-right sm:px-6">
<Divider></Divider>
</div>
{/* ------------ Mobile Number Change ---------------- */}
<div class="mt-10 sm:mt-0">
<div class="md:grid md:grid-cols-3 md:gap-6">
<div class="md:col-span-1">
<div class="px-4 sm:px-0">
<h3 class="text-lg font-medium leading-6 text-gray-900">
Change Mobile Number
</h3>
<p class="mt-1 text-sm text-gray-600">
Use a permanent address where you can receive mail.
</p>
</div>
</div>
<div class="mt-5 md:mt-0 md:col-span-2">
<form action="#" method="POST">
<div class="shadow overflow-hidden sm:rounded-md">
<div class="px-4 py-3 bg-gray-50 text-right sm:px-6">
<div class="grid grid-cols-6 gap-6">
<div class="col-span-6 sm:col-span-3">
<Buttons
title={
!editPhoneNumberState ? "Edit Phone Number" : "Cancel"
}
outline
onClick={() => {
setEditPhoneNumberState(!editPhoneNumberState);
}}
className={" flex items-center justify-center "}
/>
</div>
<div class="col-span-6 sm:col-span-3">
{editPhoneNumberState && (
<Buttons
title="Save"
onClick={async () => {
setEditPhoneNumberState(false);
await handlePhoneNumberChange();
}}
/>
)}
</div>
</div>
</div>
<div/>
<div class="px-4 py-5 bg-white sm:p-6">
{/** Email Verification */}
<div class="grid grid-cols-6 gap-6">
<div class="col-span-6 sm:col-span-3">
<label
for="first-name"
class="block text-sm font-medium text-gray-700"
>
Email
</label>
<Buttons
title="Send Email"
onClick={sendOtp}
outline
class=" inline-flex
justify-center
py-2 px-4 border
border-transparent
shadow-sm text-sm
font-medium rounded-md
text-white bg-red-400
hover:bg-red-400
focus:outline-none f
ocus:ring-2
focus:ring-offset-2
focus:ring-red-500"
/>
</div>
<div class="col-span-6 sm:col-span-3">
<label
for="last-name"
class="block text-sm font-medium text-gray-700"
>
Verification Code
</label>
<input
type="text"
name="last-name"
id="last-name"
autocomplete="family-name"
class="mt-1
focus:ring-red-400
focus:border-red-400
block w-full
shadow-sm sm:text-sm
border-gray-300 rounded-md"
/>
</div>
</div>
{/** End Email Verification */}
{/** Phone Number change */}
<div class="grid grid-cols-6 gap-6">
<div class="col-span-6 sm:col-span-3">
<label
for="first-name"
class="block text-sm font-medium text-gray-700"
>
New Mobile Number
</label>
<input
type="text"
name="first-name"
id="first-name"
autocomplete="given-name"
class="mt-1
focus:ring-red-400
focus:border-red-400
block w-full
shadow-sm sm:text-sm
border-gray-300 rounded-md"
/>
</div>
</div>
{/** End Email change */}
</div>
</div>
</form>
</div>
</div>
</div>
{/* ------------ Mobile Number Change ---------------- */}
</div>
</>
);
};
export default Security;
Above mention between two section, the password field should be added
Ok, lets assume this is your form:
import PasswordField from "/PasswordField"
const Form = () => {
const [password, setPassword] = useState("")
const [name, setName] = useState("")
const [lastName, setLastName] = useState("")
const submitForm = () => {
//your logic for submitting form
}
return (
<form onSubmit={submitForm}>
<input type="text" value={name} onChange={(e) => setName(e.target.value)} />
<input type="text" value={lastName} onChange={(e) => setLastName(e.target.value)} />
<PasswordField password={password} setPassword={setPassword} />
</form>
);
};
export default Form;
Note we are importing the PasswordField component to be used inside the form, and passing the value and the function to change that value as props to the PasswordField component.
Now lets create the Password component:
import React, {useState} from 'react';
const PasswordField = (props) => {
return (
<div>
<label class="font-medium block mb-1 mt-6 text-gray-700" for="password">
Password
</label>
<input id={"password"} type="password" value={props.password} onChange={(e) => props.setPassword(e.target.value)} />
</div>
);
};
export default PasswordField;
Obviously, you need to add your classes and styling accordingly, but I thing this could get you going.

multer gives me error "originalname" of undefined

I'm trying to make an image uploader but I'm getting this error whenever I try to upload an image. i think all the configurations I've made with multer are alright so I can't seem to find where is the error.
I'm doing this with the multer module. If anyone can help me I would really appreciate it as I've been trying to solve this error for quite a while and I keep getting the same error.
server side:
const express = require('express');
const router = express.Router();
const multer = require('multer');
const Clients = require('../models/clients.js')
const storage = multer.diskStorage({
destination: (req, file, callback) => {
callback(null, "./uploads")
},
filename: (req, file, callback) => {
callback(null, file.originalname)
}
})
const upload = multer({storage: storage})
router.route('/').get((req, res) => {
Clients.find()
.then(client => res.json(client))
.catch(err => res.status(400).json('Error:' + err))
})
router.route('/add', upload.single("articleimage")).post((req, res) => {
const newClient = new Clients({
image: req.file.originalname,
firstName: req.body.firstName,
lastName: req.body.lastName,
weight: req.body.weight,
BMI: req.body.BMI
})
newClient.save()
.then (() => res.json(newClient))
.catch(err => res.status(400).json('error' + err))
})
module.exports = router
Client side:
import React, {useState} from 'react'
import FileBase64 from 'react-file-base64';
import axios from 'axios'
function AddClient() {
const [firstName, setFirstName] = useState('')
const [lastName, setLastName] = useState('')
const [weight, setWeight] = useState('')
const [BMI, setBMI] = useState('')
const [image, setImage] = useState('')
const selectedFile = (e) => {
setImage(e.target.files[0])
}
console.log(image)
const submitForm = (e) => {
e.preventDefault()
const formData = new FormData()
formData.append("image", image)
formData.append("firstName", firstName)
formData.append("lastName", lastName)
formData.append("weight", weight)
formData.append("BMI", BMI)
axios.post('http://localhost:4000/clients/add', formData)
.then(res => console.log(res))
}
console.log(firstName)
return (
<div>
<form class="w-full max-w-lg" onSubmit={submitForm} encType="multipart/form-data">
<div class="flex flex-wrap -mx-3 mb-6">
<input type="file" filename="articleimage" onChange={selectedFile}/>
<div class="w-full md:w-1/2 px-3 mb-6 md:mb-0">
<label class="block uppercase tracking-wide text-gray-700 text-xs font-bold mb-2" for="grid-first-name">
First Name
</label>
<input class="appearance-none block w-full bg-gray-200 text-gray-700 border border-red-500 rounded py-3 px-4 mb-3 leading-tight focus:outline-none focus:bg-white" id="grid-first-name" type="text" onChange={(e) => setFirstName(e.target.value)} placeholder="First Name" />
<p class="text-red-500 text-xs italic">Please fill out this field.</p>
</div>
<div class="w-full md:w-1/2 px-3">
<label class="block uppercase tracking-wide text-gray-700 text-xs font-bold mb-2" for="grid-last-name">
Last Name
</label>
<input class="appearance-none block w-full bg-gray-200 text-gray-700 border border-gray-200 rounded py-3 px-4 leading-tight focus:outline-none focus:bg-white focus:border-gray-500" id="grid-last-name" type="text" onChange={(e) => setLastName(e.target.value)} placeholder="Last Name" />
</div>
</div>
<div class="flex flex-wrap -mx-3 mb-6">
<div class="w-full md:w-1/2 px-3 mb-6 md:mb-0">
<label class="block uppercase tracking-wide text-gray-700 text-xs font-bold mb-2" for="grid-first-name">
Weight
</label>
<input class="appearance-none block w-full bg-gray-200 text-gray-700 border border-red-500 rounded py-3 px-4 mb-3 leading-tight focus:outline-none focus:bg-white" id="grid-first-name" type="text" onChange={(e) => setWeight(e.target.value)} placeholder="Weight" />
<p class="text-red-500 text-xs italic">Please fill out this field.</p>
</div>
<div class="w-full md:w-1/2 px-3">
<label class="block uppercase tracking-wide text-gray-700 text-xs font-bold mb-2" for="grid-last-name">
Body Mass Index (BMI)
</label>
<input class="appearance-none block w-full bg-gray-200 text-gray-700 border border-gray-200 rounded py-3 px-4 leading-tight focus:outline-none focus:bg-white focus:border-gray-500" id="grid-last-name" type="text" onChange={(e) => setBMI(e.target.value)} placeholder="BMI" />
</div>
<button class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">Add Client</button>
</div>
</form>
</div>
)
}
export default AddClient
On the client-side, you are appending the formData as formData.append("image", image) but on the server-side, you are writing 'articleimage' in the upload middleware.
Change it to 'image' i.e. same as the client-side.
Also, I would suggest that the controller code for uploading/saving the image and saving the name of the image in the database should be separated.
You should create a new controller function that just saves the image on your server and returns the name of the image. Call this controller function through an API call in the selectedFile callback function. And then, save the returned name of the image in the state and finally proceed to submit the form and save the data in the database.

Warning after signup and login in ReactJS

Since I am new to ReactJS, I can't able to find why I am getting this "Warning: Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in a useEffect cleanup function." after signing up and loging in. Here is my code as follows:
AuthContext.js:
import React, { useContext, useState, useEffect } from "react";
import { auth } from "../firebase";
const AuthContext = React.createContext();
export function useAuth() {
return useContext(AuthContext);
}
export function AuthProvider({ children }) {
const [currentUser, setCurrentUser] = useState();
const [loading, setLoading] = useState(true);
function signup(email, password) {
return auth.createUserWithEmailAndPassword(email, password);
}
function login(email, password) {
return auth.signInWithEmailAndPassword(email, password);
}
useEffect(() => {
const unsubscribe = auth.onAuthStateChanged((user) => {
setCurrentUser(user);
setLoading(false);
});
return unsubscribe;
}, []);
const value = {
currentUser,
login,
signup,
};
return (
<AuthContext.Provider value={value}>
{!loading && children}
</AuthContext.Provider>
);
}
Signup.js:
import React, { useRef, useState } from "react";
import { useAuth } from "../contexts/AuthContext";
import { Link, useHistory } from "react-router-dom";
export default function Signup() {
const emailRef = useRef();
const passwordRef = useRef();
const passwordConfirmRef = useRef();
const { signup } = useAuth();
const [error, setError] = useState("");
const [loading, setLoading] = useState(false);
const history = useHistory();
async function handleSubmit(e) {
e.preventDefault();
if (passwordRef.current.value !== passwordConfirmRef.current.value) {
return setError("Passwords do not match");
}
try {
setError("");
setLoading(true);
await signup(emailRef.current.value, passwordRef.current.value);
history.push("/login");
} catch (e) {
console.error(e);
}
setLoading(false);
}
return (
<div>
<div
className="h-screen overflow-hidden flex
items-center justify-center bg-blue-300"
>
<form
onSubmit={handleSubmit}
className="space-y-5 bg-white p-16 rounded shadow w-2/3"
>
<h2 className="text-3xl mb-5 text-center text-gray-800">Sign Up</h2>
<hr />
<div class="bg-teal-200 relative text-teal-600 py-3 px-3 rounded-lg">
{error}
</div>
<label
htmlFor="email"
className="block mb-1 font-mono mt-3 text-gray-500"
>
Email
</label>
<input
ref={emailRef}
type="email"
name="email"
placeholder="Email"
className="w-full border-2 border-gray-200 p-3
rounded outline-none focus:border-blue-300"
required
/>
<label
htmlFor="password"
className="block mb-1 font-mono mt-3 text-gray-500"
>
Password
</label>
<input
ref={passwordRef}
type="password"
name="password"
placeholder="Password"
className="w-full border-2 border-gray-200 p-3
rounded outline-none focus:border-blue-300"
required
/>
<label
htmlFor="confirm password"
className="block mb-1 font-mono mt-3 text-gray-500"
>
Confirm Password
</label>
<input
ref={passwordConfirmRef}
type="password"
name="confirm-password"
placeholder="Retype Password"
className="w-full border-2 border-gray-200 p-3
rounded outline-none focus:border-blue-300"
required
/>
<hr />
<button
disabled={loading}
type="submit"
className="block w-full bg-pink-400 hover:bg-pink-300 p-4
rounded text-blck transition duration-300 font-semibold"
>
SIGN UP
</button>
<div className="w-100 text-center mt-2">
Already have an account?{" "}
<Link className="text-blue-600" to="/login">
Log In
</Link>
</div>
</form>
</div>
</div>
);
}
Login.js:
import React, { useRef, useState } from "react";
import { useAuth } from "../contexts/AuthContext";
import { Link, useHistory } from "react-router-dom";
export default function Login() {
const emailRef = useRef();
const passwordRef = useRef();
const { login } = useAuth();
const [error, setError] = useState("");
const [loading, setLoading] = useState(false);
const history = useHistory();
async function handleSubmit(e) {
e.preventDefault();
try {
setError("");
setLoading(true);
await login(emailRef.current.value, passwordRef.current.value);
history.push("/appointments");
} catch (e) {
console.error(e);
}
setLoading(false);
}
return (
<div>
<div
className="h-screen overflow-hidden flex
items-center justify-center bg-blue-300"
>
<form
onSubmit={handleSubmit}
className="space-y-5 bg-white p-16 rounded shadow w-2/3"
>
<h2 className="text-3xl mb-5 text-center text-gray-800">Log In</h2>
<hr />
<div class="bg-teal-200 relative text-teal-600 py-3 px-3 rounded-lg">
{error}
</div>
<label
htmlFor="email"
className="block mb-1 font-mono mt-3 text-gray-500"
>
Email
</label>
<input
ref={emailRef}
type="email"
name="email"
placeholder="Email"
className="w-full border-2 border-gray-200 p-3
rounded outline-none focus:border-blue-300"
/>
<label
htmlFor="password"
className="block mb-1 font-mono mt-3 text-gray-500"
>
Password
</label>
<input
ref={passwordRef}
type="password"
name="password"
placeholder="Password"
className="w-full border-2 border-gray-200 p-3
rounded outline-none focus:border-blue-300"
/>
<button
disabled={loading}
type="submit"
className="block w-full bg-pink-400 hover:bg-pink-300 p-4
rounded text-blck transition duration-300 font-semibold"
>
LOG IN
</button>
<div className="w-100 text-center mt-2">
Need an account?{" "}
<Link className="text-blue-500" to="/register">
Sign Up
</Link>
</div>
</form>
</div>
</div>
);
}
Simply because you have not make a callback after the return in useEffet which mean, your useEffect hook should be like so:
useEffect(() => {
const unsubscribe = auth.onAuthStateChanged((user) => {
if (user) {
setCurrentUser(user);
}
setLoading(false);
});
return () => unsubscribe();
}, []);

Resources