Import password filed as an functional component in ReactJs - 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.

Related

reactjs remember me functionality on localstorage

I'm having a problem here when creating a remember me function in Reactjs.
So, I managed to enter the username, password and isChecked into localstorage.
However, when I logged out, all the data in the local storage was deleted including the username, password and isChecked.
How do you make the username, password and isChecked persist after logging out? Thank You
MyCode =
import React, { useState } from "react";
import Logo from "../../../../assets/images/logo.png";
import BackgroundProfile from "../../../../assets/images/background-profile.png";
import { VscKey } from "react-icons/vsc";
import { Link } from "react-router-dom";
import { signin } from "../../../../service/account";
import { toast } from "react-toastify";
export default function CardLogin(props) {
const {
labelText,
inputText,
loginType,
firstOptionLogin,
secondOptionLogin,
labelIcon,
firstRoute,
secondRoute,
firstIcon,
secondIcon,
} = props;
const [username, setUsername] = useState(() =>
localStorage.checkbox ? localStorage.username : ""
);
const [password, setPassword] = useState(() =>
localStorage.checkbox ? localStorage.password : ""
);
const [isChecked, setIsChecked] = useState(() => !!localStorage.checkbox);
const initialValue = {
username: username,
password: password,
nik: "",
};
const [isLoading, setIsLoading] = useState(false);
const handleSubmit = () => {
if (isChecked && username !== "") {
localStorage.username = username;
localStorage.password = password;
localStorage.checkbox = isChecked ? "1" : "";
}
const data = new URLSearchParams();
console.log(loginType);
if (loginType === "username") {
data.append("username", initialValue.username);
data.append("password", initialValue.password);
data.append("grant_type", "password");
}
setIsLoading(true);
signin(data, loginType)
.then((response) => {
if (response?.code === 200) {
console.log(response);
localStorage.setItem(
"accessToken",
JSON.stringify(response.data.accessToken)
);
localStorage.setItem(
"userSession",
JSON.stringify(response.data.accessTokenExpiresAt)
);
window.location.reload();
} else {
toast.error(response.message);
}
})
.catch((error) => {
console.log(error);
})
.finally(() => {
setIsLoading(false);
});
};
return (
<div
style={{
backgroundSize: "100% 75%",
backgroundRepeat: "no-repeat",
height: "100%",
backgroundImage: `url(${BackgroundProfile})`,
}}
>
{/* Button Back on The Top of Page */}
<button>
<div className="rounded-full w-5 md:w-10 h-5 md:h-10 p-3 relative top-2 left-2">
{/* <FaArrowLeft className="text-[#DD2729] text-xs md:text-base absolute top-1/2 left-1/2 -translate-y-1/2 -translate-x-1/2" /> */}
</div>
</button>
{/* Logo & Card Login */}
<img
src={Logo}
className="absolute top-6 bottom-6 right-4 w-2/5 md:w-1/5"
alt="Logo"
/>
<div className="mx-auto mt-8 w-3/5 md:w-2/5 bg-white px-5 py-3 md:px-8 md:py-5 rounded-md drop-shadow-xl">
<button>
{/* <FaArrowLeft className="text-[#DD2729] text-xs md:text-base" /> */}
</button>
<article
style={{ fontFamily: "ubuntu" }}
className="text-center text-[#808285] text-xs md:text-lg"
>
Selamat Datang! <br /> Silakan masuk untuk mulai menggunakan aplikasi
</article>
{/* Form Login*/}
<form onSubmit={handleSubmit} className="pt-3 md:pt-5">
<div>
<label
htmlFor={loginType}
className="text-[#424242] text-xs md:text-sm "
>
{labelText}
</label>
<div className="flex">
<div
className={`w-10 flex items-center justify-center bg-blue-lighter border-y border-l border-[#9E9E9E] rounded-l text-blue-dark`}
>
{labelIcon}
</div>
<input
id="username"
name="username"
type="text"
placeholder={inputText}
value={username}
onChange={(e) => setUsername(e.target.value)}
className={`w-full border-l-0 border-[#9E9E9E] rounded-r text-xs md:text-lg font-sans`}
/>
</div>
</div>
<div className="pt-2 md:pt-3">
<label
htmlFor="password"
className="text-[#424242] text-xs md:text-sm"
>
Password
</label>
<div className="flex">
<div
className={`w-10 flex items-center justify-center bg-blue-lighter border-y border-l border-[#9E9E9E] rounded-l text-blue-dark `}
>
<VscKey className="text-[#A8A8A8] text-xl" />
</div>
<input
id="password"
name="password"
type="password"
placeholder="Masukkan kata sandi anda"
value={password}
onChange={(e) => setPassword(e.target.value)}
className={`w-full border-l-0 border-[#9E9E9E] rounded-r text-xs md:text-lg font-normal `}
/>
</div>
</div>
{/* End of Form Login */}
{/* Remember me & Forgot Password */}
<div className="flex pt-3 items-center justify-between">
<div className="flex items-center gap-1.5">
<input
type="checkbox"
checked={isChecked}
name="lsRememberMe"
onChange={(e) => setIsChecked(e.target.checked)}
className="rounded"
/>
<label htmlFor="" className="text-xs md:text-sm">
Remember me
</label>
</div>
<div className="">
<Link
to="/forgot-password"
className="text-xs md:text-sm underline underline-offset-1 font-bold"
>
Forgot password
</Link>
</div>
</div>
<input
type="submit"
value={isLoading ? "Loading" : "Masuk"}
disabled={isLoading}
className="bg-[#EA001E] hover:bg-[#F55151] active:bg-[#BA0D0D] w-full text-white font-bold text-md rounded-lg p-2 mt-4 shadow-xl cursor-pointer text-xs md:text-sm"
/>
</form>
{/* End of Remember me & Forgot Password */}
{/* Login Option */}
<div className="mt-3">
<h4 className="login-selection text-center text-xs md:text-sm">
or login with
</h4>
</div>
<div className="flex items-center justify-center gap-2 mt-4">
<Link to={firstRoute}>
<div className="flex items-center justify-around gap-2 bg-white shadow-xl rounded-full py-2 px-3 md:px-8">
<img
src={firstIcon}
alt="Login Icons"
className="w-2/6 md:w-4/5"
/>
<div className="font-bold text-xs md:text-sm uppercase">
{firstOptionLogin}
</div>
</div>
</Link>
<Link to={secondRoute}>
<div className="flex items-center justify-around gap-2 bg-white shadow-xl rounded-full py-2 px-3 md:px-10">
<img
src={secondIcon}
alt="Login Icons"
className="w-2/6 md:w-4/5"
/>
<div className="font-bold text-xs md:text-sm uppercase">
{secondOptionLogin}
</div>
</div>
</Link>
</div>
{/* End of Login Option */}
{/* Alternative Register */}
<div className="flex items-center justify-center gap-2 mt-4 text-xs md:text-sm">
<p>Don't have an account?</p>
<Link
to="/signup"
className="text-[#DE1B1B] font-bold text-xs md:text-sm"
>
Sign Up
</Link>
</div>
{/* End of Alternative Register */}
</div>
</div>
);
}
CASE CLOSED, in the form section onSubmit={handleSubmit} I delete it to just form, then onSubmit={handleSubmit} I move it to button to become onClick={handleSubmit}.
thank you for answering my question. i appreciate it

Passing values from a constant to the e.target.value

I am working on building out a radio component and when checked I want the values from the radio button to pass when set onBlur. I am trying to pass a function to the onBlur but I am not seeing the values on my Form Submit action.
const [isChecked, setIsChecked] = React.useState<boolean>(defaultValue);
const onValue = React.useMemo(() => {
if (!isChecked) return [`${label}, ${description}`];
}, [onChange]);
const checkedValue = React.useCallback(
(e: React.ChangeEvent<HTMLInputElement>) =>
onChange?.(onValue, e.target.value),
[onChange]
);
return (
<div className="space-y-5">
<div className="relative flex items-start">
<div key={id} className="flex h-5 items-center">
<input
id={`${label}-id`}
name={label}
type="radio"
className="h-4 w-4 border-gray-300 text-indigo-600 focus:ring-indigo-500"
onBlur={checkedValue)}
onChange={() => setIsChecked(!isChecked)}
/>
</div>
<div className="ml-3 text-sm">
<label
htmlFor={`${label}-id`}
className="block font-medium text-gray-700"
>
{label}
</label>
<p id={`${label}-description`} className="text-gray-500">
{description}
</p>
</div>
</div>
</div>
);
};

After browser relode i got the user profile pic in website.how can i get it first time without browser reloding

**
import { useForm } from "react-hook-form";
import React, { useState } from "react";
import { useEffect } from "react";
import { useUpdateProfile } from "react-firebase-hooks/auth";
import { ref, uploadBytesResumable, getDownloadURL } from "firebase/storage";
import {
useCreateUserWithEmailAndPassword,
useSignInWithGoogle,
} from "react-firebase-hooks/auth";
import auth, { storage } from "../../firebase.init";
import { Link, useLocation, useNavigate } from "react-router-dom";
import Loader from "../Shared/Loader";
const Register = () => {
const [image, setImage] = useState(null);
const [url, setUrl] = useState(null);
const [percentage, setPercentage] = useState("");
const [updateProfile, updating] = useUpdateProfile(auth);
const [signInWithGoogle, gUser, gLoading] = useSignInWithGoogle(auth);
const [
createUserWithEmailAndPassword,
user,
loading,
error,
] = useCreateUserWithEmailAndPassword(auth);
const navigate = useNavigate();
const { register, handleSubmit, formState } = useForm({
mode: "onChange", // I want to change it to onBlur
});
const { isValid, errors } = formState;
const handleimagechange = (e) => {
if (e.target.files[0]) {
setImage(e.target.files[0]);
}
};
**useEffect(() => {
if (user?.user?.uid) {
navigate("/appiontment");
window.location.reload();
}
}, [user?.user?.uid, navigate]);
useEffect(() => {
if (gUser?.user?.uid) {
navigate("/appiontment");
}
}, [gUser?.user?.uid, navigate]);**
**useEffect(() => {
const uploadImage = () => {
// const name = new Date().getTime + image.name
const storageRef = ref(storage, image.name);
const uploadTask = uploadBytesResumable(storageRef, image);
uploadTask.on(
"state_changed",
(snapshot) => {
const progress =
(snapshot.bytesTransferred / snapshot.totalBytes) * 100;
setPercentage(progress);
switch (snapshot.state) {
case "paused":
break;
case "running":
break;
default:
break;
}
},
(error) => {},
() => {
getDownloadURL(uploadTask.snapshot.ref).then((downloadURL) => {
console.log("File available at", downloadURL);
setUrl(downloadURL);
});
}
);
};
image && uploadImage();
}, [image]);**
let singninErrors;
if (error?.message === "Firebase: Error (auth/email-already-in-use).") {
singninErrors = (
<div
className="bg-red-100 rounded-lg py-5 px-6 mb-4 text-base text-red-700 mb-3"
role="alert"
>
Email already Exsist
</div>
);
console.log(error.message);
}
**const onSubmit = async (data) => {
await createUserWithEmailAndPassword(data.email, data.password, data.name);
await updateProfile({ displayName: data.name, photoURL: url });
};
if (error) {
console.log(error.message);
}**
if (loading || gLoading || updating) {
return <Loader />;
}
return (
<div className="flex h-screen justify-center items-center ">
<div className="card w-96 bg-base-100 shadow-xl">
<div className="card-body">
<div className="flex flex-col w-full border-opacity-50">
<h1 className="text-xl text-center">Sign Up</h1>
<form onSubmit={handleSubmit(onSubmit)}>
<div className="form-control w-full max-w-xs ">
<label className="label">
<span className="label-text">Name</span>
</label>
<input
{...register("name", {
required: {
value: true,
message: "Name is required",
},
})}
type="text"
placeholder="Your Name"
className="input input-bordered w-full max-w-xs"
/>
<label className="label">
{errors.name?.type === "required" && (
<span className="label-text text-red-500">
{errors.name.message}
</span>
)}
</label>
</div>
<div className="form-control w-full max-w-xs ">
<label className="label">
<span className="label-text">Email</span>
</label>
<input
{...register("email", {
required: {
value: true,
message: "Email Adress is required",
},
pattern: {
value: /^[^\s#]+#[^\s#]+\.[^\s#]+$/,
message: "please enter a valid email adress",
},
})}
type="email"
placeholder="Your Email"
className="input input-bordered w-full max-w-xs"
/>
<label className="label">
{errors.email?.type === "required" && (
<span className="label-text text-red-500">
{errors.email.message}
</span>
)}
{errors.email?.type === "pattern" && (
<span className="label-text text-red-500">
{errors.email.message}
</span>
)}
</label>
</div>
<div className="form-control w-full max-w-xs ">
<label className="label">
<span className="label-text">Password</span>
</label>
<input
{...register("password", {
required: {
value: true,
message: "password is required",
},
minLength: {
value: 6,
message: "password must be 6 character or long",
},
})}
type="password"
placeholder="Your password"
className="input input-bordered w-full max-w-xs"
/>
<label className="label">
{errors.password?.type === "required" && (
<span className="label-text text-red-500">
{errors.password.message}
</span>
)}
{errors.password?.type === "minLength" && (
<span className="label-text text-red-500">
{errors.password.message}
</span>
)}
</label>
</div>
<label className="label">Upload Your Avatar</label>
<div className="w-full bg-gray-200 rounded-full">
{percentage === 0 && (
<div
className="bg-blue-100 rounded-lg py-5 px-6 mb-4 text-base text-blue-700
mb-3"
role="alert"
>
Image Uploading please wait
</div>
)}
{percentage === 100 && url && (
<div
className="bg-green-100 rounded-lg py-5 px-6 mb-4 text-base text-green-700
mb-3"
role="alert"
>
img Uploading:{percentage}% Successfully
</div>
)}
</div>
<div className="flex justify-center">
<div className="mb-3 w-96 ">
<input
onChange={handleimagechange}
className="form-control block
w-full
px-3
py-1.5
text-base
font-normal
text-gray-700
bg-white bg-clip-padding
border border-solid border-gray-300
rounded
transition
ease-in-out
m-0
focus:text-gray-700 focus:bg-white focus:border-blue-
600 focus:outline-none"
type="file"
id="formFile"
/>
</div>
</div>
{singninErrors}
<button
disabled={!isValid || !url}
type="submit"
className="btn w-full max-w-xs">
Signup</button> </form>
<p className="font-semibold ">
<small>
already have an account ?
<Link className="text-secondary mx-2" to="/">
Please login
</Link>
</small>
</p>
<div className="divider">OR</div>
<button
onClick={() => signInWithGoogle()}
className="btn btn-outline"
>
Continue with Google
</button>
</div>
</div>
</div>
</div>
);
};
export default Register;
**

Nextjs redirecting and updating changes not working in strapi apollo graphql authentication

I am implementing authentication on nextjs strapi graphql and I want to redirect user once he registers or logins or theres is jwt token in cookies but when I login. its not redirecting using router.push method, I am also checking in other pages if user exist in cookies but use`Effect not working Here is my code example
System Information
4.1.11:
Macos:
Mysql:
14.17.00:
6.14.13:
1.22.19:
import { useContext, useEffect, useState } from "react";
import Image from "next/image";
import Link from "next/link";
import { useMutation } from "#apollo/client";
import { LOGIN_USER } from "../../gql/mutations";
import { userContext } from "../../context/wrapppers/UserWrapper";
import { setUserAction } from "../../context/actions/user-actions";
import { SIGN_IN } from "../../context/actions/action-types";
import { useRouter } from "next/router";
function login() {
const router = useRouter();
const { user, dispatchUser } = useContext(userContext);
const [credentials, setCredentials] = useState({});
useEffect(() => {
if (user !== "" && user !== undefined) {
router.push("/account");
}
}, []);
const [loginUser, { loading, error, data }] = useMutation(LOGIN_USER);
useEffect(() => {
if (data) {
dispatchUser(
setUserAction(
{
token: data.login.jwt,
username: data.login.user.username,
id: data.login.user.id,
email: data.login.user.email,
},
SIGN_IN
)
);
}
}, [data]);
if (loading) return <h1>logging in...</h1>;
if (error) return <h1>{error.message}</h1>;
console.log("user from login page", user);
const handleChange = (e) => {
setCredentials({
...credentials,
[e.target.name]: e.target.value,
});
};
const handleLogin = (e) => {
if (typeof window === "undefined") {
return;
}
e.preventDefault();
loginUser({
variables: {
input: credentials,
},
});
};
return (
<div className="h-screen bg-slate-50 flex justify-center items-center w-full">
{error && <div>{error.message}</div>}
<form onSubmit={handleLogin}>
<div className="bg-white px-10 py-8 rounded-xl w-screen shadow-md max-w-sm">
<Image
src={require("../../public/Img/logo.png")}
height={50}
objectFit="contain"
className="h-14 mb-4 mx-auto"
alt=""
/>
<div className="space-y-4">
<h1 className="text-center text-2xl font-semibold text-gray-600">
Login
</h1>
<div>
<label
for="email"
className="block mb-1 text-gray-600 font-semibold"
>
Email or Username
</label>
<input
name="identifier"
onChange={handleChange}
type="text"
required
className="bg-indigo-50 px-4 py-2 outline-none rounded-md w-full"
/>
</div>
<div>
<label
for="password"
className="block mb-1 text-gray-600 font-semibold"
>
Password
</label>
<input
name="password"
onChange={handleChange}
type="text"
required
className="bg-indigo-50 px-4 py-2 outline-none rounded-md w-full"
/>
</div>
</div>
<button
type="submit"
className="mt-4 w-full bg-yellow-500 font-semibold py-2 rounded-md tracking-wide"
>
Login
</button>
<Link href="account/register">
<h3 className="mt-2 cursor-pointer">Or Create an account</h3>
</Link>
</div>
</form>
</div>
);
}
export default login;
function index() {
const router = useRouter();
const { user, dispatchUser } = useContext(userContext);
const [getUserOrders, { loading, error, data }] = useLazyQuery(USER_ORDERS);
useEffect(() => {
if (user) {
getUserOrders({
variables: {
filters: {
user: {
id: {
eq: user.id,
},
},
status: {
ne: "rejected",
},
},
},
});
} else {
router.push("/account/login");
}
}, [user]);
if (error) return <div>{error.message}</div>;
if (loading) return <div>Loading ...</div>;
const handleLogout = () => {
router.push("/account/login");
dispatchUser(setUserAction(user, SIGN_OUT));
};
return (
<div>
<section className="py-5 sm:py-7 bg-gray-100">
<div className="container max-w-screen-xl mx-auto px-4">
Home/Account
</div>
</section>
<section className="py-10">
<div className="container max-w-screen-xl mx-auto px-4">
<div className="flex flex-col md:flex-row -mx-4">
<aside className="md:w-1/3 lg:w-1/4 px-4">
<ul>
<li>
<Link href="/account">
<span className="block px-3 py-2 text-primary bg-gray-100 hover:bg-orange-100 rounded-md">
Account
</span>
</Link>
</li>
<li>
<div
className="cursor-pointer flex items-center"
onClick={handleLogout}
>
<IoIosLogOut size="20" className="mr-2" />
<span>Log out</span>
</div>
</li>
</ul>
</aside>
<main className="md:w-2/3 lg:w-3/4 px-4">
<article className="border border-gray-200 bg-white shadow-sm rounded mb-5 p-3 lg:p-5">
<figure className="flex items-start sm:items-center">
<AiOutlineUser size="50" />
<figcaption>
<h5 className="font-semibold text-lg">
Hi {user.username}
</h5>
<p>Email: {user.email}</p>
</figcaption>
</figure>
<hr className="my-4" />
<h3 className="text-xl font-semibold mb-5">Order History</h3>
{data && data.orders.data.length !== 0 ? (
data.orders.data.map(({ id, attributes }, orderIndex) => (
<article
key={id}
className="p-3 lg:p-5 mb-5 bg-white border border-blue-600 rounded-md"
>
<header className="lg:flex justify-between mb-4">
<div className="mb-4 lg:mb-0">
<p className="font-semibold">
<span>Order ID: #{id} </span>
<span className="text-green-500">
{" "}
• {attributes.status}{" "}
</span>
</p>
<p className="text-gray-500">
{" "}
{new Date(
attributes.createdAt
).toLocaleDateString()}
</p>
</div>
</header>
<hr className="my-4" />
<div className="grid md:grid-cols-2 lg:grid-cols-3 gap-2">
{attributes.products.data.map(
({ id, attributes }, productIndex) => (
<Link href={`/shop/${attributes.slug}`}>
<figure
key={id}
className="flex flex-row mb-4 cursor-pointer"
>
<div>
<Image
src={`${
BACKEND_URL +
attributes.media.data[0].attributes.url
}`}
width={80}
height={80}
objectFit="cover"
className="rounded"
/>
</div>
<figcaption className="ml-3">
<p className="text-gray-600">
{attributes.name}
</p>
<p className="mt-1 font-semibold">
{
data.orders.data[orderIndex].attributes
.details[productIndex].quantity
}{" "}
x ${attributes.price}
</p>
</figcaption>
</figure>
</Link>
)
)}
</div>
</article>
))
) : (
<EmptyState
title="You have not yet ordered"
subtitle="Choose some products to order"
image={EmptyOrder}
btnText="Go to shop"
btnText2="Go Home"
btnLink="/shop"
btnLink2="/"
/>
)}
</article>
</main>
</div>
</div>
</section>
</div>
);
}
export default index;
I am quite new in nextjs and graphql any suggesstion highly appreciated!

Next.js form reCAPTCHA returns window of undefined - react-hook-recaptcha

I am trying to implement reCAPTCHA using the react-hook-form in combination with react-hook-recaptcha Not sure what is the reason but I am getting the following error for window saying it's undefined:
ReferenceError: window is not defined
> 33 | const { recaptchaLoaded, recaptchaWidget } = useRecaptcha({
Code:
import React, { useState } from "react";
import { useRecaptcha } from "react-hook-recaptcha";
import { useForm, SubmitHandler } from "react-hook-form";
import { urlFor } from "#lib/sanity";
import { dateFormat } from "#lib/helpers";
import { PortableText } from "#portabletext/react";
import { portableTextComponents } from "#components/portable-text";
import { FormError, FormSuccess } from "#components/Form";
import { ArticleProps, Comment } from "types/article";
const sitekey = "6Ld-*********"; // change to your site key
const containerId = "recaptcha"; // this id can be customized
declare global {
interface Window {
grecaptcha: any;
}
}
const ArticleSingle = ({ page }: ArticleProps) => {
const [submitted, setSubmitted] = useState(false);
const { _id, body, featuredImage, title, author, publishedAt, comments } =
page;
const successCallback = (response: any) => {
console.log("YUP");
};
const { recaptchaLoaded, recaptchaWidget } = useRecaptcha({
containerId,
successCallback,
sitekey,
size: "invisible",
});
const executeCaptcha = () => {
if (recaptchaWidget !== null) {
window.grecaptcha.reset(recaptchaWidget);
window.grecaptcha.execute(recaptchaWidget);
}
};
const {
register,
handleSubmit,
formState: { errors },
} = useForm<Comment>();
const onSubmit: SubmitHandler<Comment> = async (e, data) => {
e.preventDefault();
executeCaptcha();
fetch("/api/create-comment", {
method: "POST",
body: JSON.stringify(data),
})
.then(() => {
console.log(data);
setSubmitted(true);
})
.catch((error) => {
console.log(error);
setSubmitted(false);
});
};
return (
<div id="article">
<div className="relative mb-4 md:mb-0" style={{ height: "45rem" }}>
<div
className="absolute bottom-0 left-0 z-10 w-full h-full"
style={{
backgroundImage:
"linear-gradient(180deg,transparent,rgba(0,0,0,.75))",
}}
></div>
{featuredImage && featuredImage.asset && (
<img
alt={featuredImage?.alt || ""}
src={urlFor(featuredImage).quality(85).url()}
className="absolute top-0 left-0 z-0 object-cover w-full h-full"
/>
)}
<div className="absolute left-0 right-0 z-20 max-w-screen-lg p-4 mx-auto bottom-2">
{title && (
<h1 className="text-4xl font-semibold leading-tight text-gray-100 md:text-5xl lg:text-7xl">
{title}
</h1>
)}
<div className="flex gap-5 mt-5 place-items-center">
{author?.featuredImage && (
<img
className="object-cover object-center w-12 h-12 border-2 border-white rounded-full shadow-lg md:w-16 md:h-16"
alt={author?.featuredImage?.alt || ""}
src={urlFor(author.featuredImage).quality(85).url()!}
/>
)}
<div>
{author && (
<p className="font-semibold text-gray-200 sm:text-md md:text-xl">
{author.name}
</p>
)}
{publishedAt && (
<time className="font-semibold text-bubblegum sm:text-md md:text-xl">
{dateFormat(publishedAt)}
</time>
)}
</div>
</div>
</div>
</div>
<div className="max-w-screen-lg px-4 pb-8 mx-auto mt-12 text-navyBlue text-md md:text-xl md:leading-relaxed">
<PortableText value={body} components={portableTextComponents} />
{/* Comment Form */}
<div id="article-comments">
<hr className="my-5 mb-10 border border-yellow-500" />
{submitted ? (
<FormSuccess
title="Thank you for submitting your comment!"
message="Once it has been approved, it will appear below!"
/>
) : (
<>
<h3 className="text-md text-bubblegum">Enjoyed this article?</h3>
<h4 className="text-3xl font-bold">Leave a comment below!</h4>
<hr className="py-3 mt-2" />
<form
className="flex flex-col pb-5 mx-auto"
onSubmit={handleSubmit(onSubmit)}
>
<input
{...register("_id")}
type="hidden"
name="_id"
value={_id}
/>
<input
{...register("name", {
required: "The Name Field is required",
})}
className="block w-full px-3 py-2 mt-4 border rounded shadow outline-none form-input ring-bubblegum focus:ring"
placeholder="Name"
type="text"
/>
{errors.name && <FormError message={errors.name.message} />}
<input
{...register("email", {
required: "The Email Field is required",
pattern: {
value: /^[A-Z0-9._%+-]+#[A-Z0-9.-]+\.[A-Z]{2,4}$/i,
message: "Enter a valid e-mail address",
},
})}
className="block w-full px-3 py-2 mt-4 border rounded shadow outline-none form-input ring-bubblegum focus:ring"
placeholder="Email"
type="email"
/>
{errors.email && <FormError message={errors.email.message} />}
<textarea
{...register("comment", {
required: "The Comment Field is required",
minLength: {
value: 40,
message: "A Min of 40 characters is required",
},
})}
className="block w-full px-3 py-2 mt-4 border rounded shadow outline-none resize-none form-textarea ring-bubblegum focus:ring"
placeholder="Comment"
rows={7}
/>
{errors.comment && (
<FormError message={errors.comment.message} />
)}
<input
disabled={!recaptchaLoaded}
type="submit"
className="flex-none w-32 px-4 py-2 mt-6 text-xs font-bold text-center uppercase duration-300 ease-in-out bg-transparent border-2 rounded-full cursor-pointer text-navyBlue border-navyBlue hover:bg-navyBlue hover:text-bubblegum"
></input>
</form>
{/* Comments */}
{comments.length > 0 && (
<div className="flex flex-col my-10">
<h3 className="text-4xl">Comments</h3>
<hr className="mt-2 mb-5 border-2 border-yellow-500" />
{comments.map(({ name, _id, _createdAt, comment }) => (
<div
className="px-4 py-6 bg-white rounded-sm shadow-md"
key={_id}
>
<p>
<time className="block text-sm font-bold">
{dateFormat(_createdAt)}{" "}
</time>
<span className="text-bubblegum">{name}</span> :
<span className="pl-2">{comment}</span>
</p>
</div>
))}
</div>
)}
</>
)}
</div>
</div>
</div>
);
};
export default ArticleSingle;
Next.js has a server-side environment, and window object only exists in the browser. You can check which environment code is running with this:
const isServerSide = typeof window === 'undefined'
So your code will probably look like:
const executeCaptcha = () => {
if (recaptchaWidget !== null && typeof window !== 'undefined') {
window.grecaptcha.reset(recaptchaWidget);
window.grecaptcha.execute(recaptchaWidget);
}
};

Resources