Warning after signup and login in ReactJS - 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();
}, []);

Related

Black screen in react code - possible firebase auth issue

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

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;
});

Uncaught TypeError: Cannot destructure property 'connectWallet' of 'useContext(...)' as it is undefined

So basically when i try to fill the form and exchange between two accounts , nothing happens
and when i check the console sometimes there's no error appearing and sometimes there's this one "Uncaught TypeError: Cannot destructure property 'connectWallet' of 'useContext(...)' as it is undefined." , and there's no data being destructered and sent to the browser , it's empty enter image description here
and it triggers "no accounts found"
this is the console after and click "send"
enter image description here
this is my code:
TransactionContext.jsx :
import React, {useEffect, useState} from 'react';
import {ethers} from 'ethers';
import {contractABI, contractAddress} from '../utils/constants';
export const TransactionContext = React.createContext();
const {ethereum} = window;
const getEthereumContract = () => {
const provider = new ethers.providers.Web3Provider(ethereum);
const signer = provider.getSigner();
const transactionContract = new ethers.Contract(contractAddress, contractABI, signer);
return transactionContract;
}
export const TransactionProvider = ({children}) => {
const [currentAccount, setCurrentAccount] = useState('');
const [formData, setFormData] = useState({addressTo: '', amount: '', keyword: '', message: ''});
const [isLoading, setIsLoading] = useState(false);
const [transactionCount, setTransactionCount] = useState(localStorage.getItem('transactionCount'));
const handleChange = (e, name) => {
setFormData((prevState) => ({ ...prevState, [name]: e.target.value }));
}
const checkIfWalletIsConnected = async () => {
try{
if(!ethereum) return alert("please install metamask");
const accounts = await ethereum.request({method: 'eth_accounts'});
if(accounts.length) {
setCurrentAccount(accounts[0]);
}
else {
console.log('no accounts found');
}
}
catch (error) {
console.log(error);
throw new Error("No ethereum object.")
}
};
const connectWallet = async () => {
try{if(!ethereum) return alert("please install metamask");
const accounts = await ethereum.request({method: 'eth_requestAccounts'});
setCurrentAccount(accounts[0]);}
catch (error){
console.log(error);
throw new Error("No ethereum object.")
}
}
const sendTransaction = async () => {
try{if(!ethereum) return alert("please install metamask");
const {addressTo, amount, keyword, message } = formData;
const transactionContract = getEthereumContract();
const parseAmount = ethers.utils.parseEther(amount);
await ethereum.request({
method: 'eth_sendTransaction',
params: [{
from: currentAccount,
to: addressTo,
gas: '0x5208',
value: parseAmount._hex,
}]
});
const transactionHash = await transactionContract.addToBlockChain(addressTo, parseAmount, message, keyword);
setIsLoading(true);
console.log('Loading - ${transactionHash.has}');
await transactionHash.wait();
setIsLoading(false);
console.log('success - ${transactionHash.has}');
const transactionCount = await transactionContract.getTransactionCount();
setTransactionCount(transactionCount.toNumber());
}
catch(error) {
console.log(error);
throw new Error("No ethereum object.")
}
}
useEffect( () => {
checkIfWalletIsConnected();
}, []);
return (
<TransactionContext.Provider value={{connectWallet, currentAccount, formData, setFormData, handleChange, sendTransaction}}>
{children}
</TransactionContext.Provider>
);
}
Welcome.jsx
import {AiFillPlayCircle} from 'react-icons/ai';
import {SiEthereum} from 'react-icons/si';
import {BsInfoCircle} from 'react-icons/bs';
import {Loader} from './';
import { TransactionContext } from '../context/TransactionContext';
import React, {useContext} from 'react';
const commonStyles = "min-h-[70px] sm:px-0 px-2 sm:min-w-[120px] flex justify-center items-center border-[0.5px] border-gray-400 text-sm font-light text-white";
const Input = ({placeholder, name, type, value, handleChange}) => (
<input
placeholder={placeholder}
type={type}
step="0.0001"
value={value}
onChange={(e) => handleChange(e, name)}
className="my-2 w-full rounded-sm p-2 outline-none bg-transparent text-white border-none text-sm white-glassmorphism" />
);
const Welcome = () => {
const {connectWallet, currentAccount, formData, sendTransaction, handleChange} = useContext(TransactionContext);
const handleSubmit = (e) => {
const { addressTo, amount, keyword, message } = formData;
e.preventDefault();
if(!addressTo || !amount || !keyword || !message) return;
sendTransaction();
};
return (
<div className="flex w-full justify-center items-center">
<div className="flex mf:flex-row flex-col items-start justify-between md:p-20 py-12 px-4">
<div className="flex flex-1 justify-start flex-col mf:mr-10 ">
<h1 className="text-3xl sm:text-5xl text-white text-gradient py-1">
Send Crypto <br/> across the world
</h1>
<p className="text-left mt-5 text-white font-light md:w-9/12 w-11/12 text-base">
Explore the universe of crypto trade cryptocurrencies smoothly and securely on Krypto
</p>
{!currentAccount && (<button type="button" onClick={connectWallet}
className="flex flex-row justify-center items-center my-5 bg-[#2952e3] p-3 rounded-full cursor-pointer hover:bg-[2546bd]">
<p className="text-white text-base font-semibold" >Connect Your Wallet </p>
</button>)}
<div className="grid sm:grid-cols-3 grid-cols-2 w-full mt-10">
<div className={`rounded-tl-2xl ${commonStyles}`}>
Reliability
</div>
<div className={commonStyles}>
Security
</div>
<div className={`rounded-tr-2xl ${commonStyles}`}>
Ethereum
</div>
<div className={`rounded-bl-2xl ${commonStyles}`}>
Web 3.0
</div>
<div className={commonStyles}>
Low fees
</div>
<div className={`rounded-br-2xl ${commonStyles}`}>
Blockchain
</div>
</div>
</div >
<div className="flex flex-col flex-1 items-center justify-start w-full mf:mt-0 mt-10">
<div className="p-3 justify-end items-start flex-col rounded-xl h-40 sm:w-72 w-full my-5 eth-card white-glassmorphism">
<div className="flex justify-between flex-col w-full h-full">
<div className="flex justify-between items-start">
<div className="w-10 h-10 rounded-full border-2 border-white flex justify-center items-center">
<SiEthereum fontSize={21} color="#fff"/>
</div>
<BsInfoCircle fontSize={17} color="fff"/>
</div>
<div>
<p className="text-white font-light text-sm ">
Address
</p>
<p className="text-white font-semibold text-lg mt-1 ">
Ethereum
</p>
</div>
</div>
</div>
<div className="p-5 sm:w-96 w-full flex flex-col justify-start items-center blue-glassmorphism">
<Input placeholder="Address to" name="addressTo" type="text" handleChange={handleChange} />
<Input placeholder="Amount of (ETH) " name="amount" type="number" handleChange={handleChange} />
<Input placeholder="Keyword (Gif)" name="Keyword" type="text" handleChange={handleChange} />
<Input placeholder="Enter message" name="message" type="text" handleChange={handleChange} />
<div className ="h-[1px] w-full bg-gray-400 my-2"/>
{false ? (
<Loader/>
) : (
<button
type="button" onClick={handleSubmit}
className="text-white w-full mt-2 border-[1px] p-2 border-[#3d4f7c] rounded-full cursor-pointer">
Send
</button>
)}
</div>
</div>
</div>
</div>
);
}
export default Welcome;
Main.jsx
import React from 'react'
import ReactDOM from 'react-dom'
import App from './App'
import './index.css'
import {TransactionProvider} from './context/TransactionContext';
ReactDOM.render(
<TransactionProvider>
<React.StrictMode>
<App />
</React.StrictMode>
</TransactionProvider>,
document.getElementById('root')
)

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.

Resources