What I want to do here is to check if the email provided is valid or not, and then notify user based on this email validation.
Code:
const RightUI = () => {
const [email, setEmail] = useState("");
const [isValidEmail, setIsValidEmail] = useState(undefined);
const handleFormSubmit = (e) => {
e.preventDefault();
const isValid =
/^((([!#$%&'*+-/=?^_`{|}~w])|([!#$%&'*+-/=?^_`{|}~w][!#$%&'*+-/=?^_`{|}~.w]{0,}[!#$%&'*+-/=?^_`{|}~w]))[@]w+([-.]w+)*.w+([-.]w+)*)$/gm.test(
email
);
setIsValidEmail(isValid);
};
useEffect(() => {
console.log(isValidEmail)
if (isValidEmail) {
setTimeout(() => {
window.location = "https://google.com";
}, 2500);
}
}, [isValidEmail]);
return (
<div id="right__ui">
<div className="right__ui-container">
<h3>Sign up for exclusive access.</h3>
<form onSubmit={handleFormSubmit}>
<input
type="text"
placeholder="Your email address"
id="email_input"
value={email}
onChange={(e) => setEmail(e.target.value)}
/>
<button type="submit">Get Started</button>
</form>
{isValidEmail === undefined ? null : (
<NotifyUser
msg={
isValidEmail
? "Thanks for providing your details."
: "Please provide a valid Email address!"
}
type={isValidEmail ? "success" : "error"}
timeout={3000}
/>
)}
</div>
</div>
);
};
NotifyUser.js
import { useState, useEffect } from "react";
import "./notifyUser.css";
const NotifyUser = ({ msg, type, timeout }) => {
const [isVisible, setIsVisible] = useState(true);
useEffect(() => {
const timer = setTimeout(() => {
setIsVisible(false);
}, timeout);
return () => {
clearTimeout(timer);
};
}, [timeout]);
const notificationStyle = {
backgroundColor: notification[type][0],
color: notification[type][1],
};
return (
<>
{isVisible && (
<div
className="notification-box"
role="alert"
style={notificationStyle}
>
{msg}
</div>
)}
</>
);
};
const notification = {
error: ["#ecc8c5", "#ab3331"],
success: ["#d4edda", "#155724"],
info: ["#cce5ff", "#004085"],
};
export default NotifyUser;
The Problem: NotifyUser
component renders the very first time (based on the email validation), but after that it does not render. I am new to React, and this part of my learning project, I understand that I am doing something fundamentally wrong here due to lack of my knowledge. Please enlighten me.
2
Answers
I guess the problem is that you conditionally render the component by making the ternary expression
isValidEmail === undefined ? null : (...
which will only work the first time the email is validated because only the first time the "isValidEmail" equals undefined since it’s the initial state but after if the email is not valid the "isValidEmail" will be false not undefinedso the problem is you checking against the wrong falsy value
you should make the condition as
isValidEmail && (component code here)
and better to set the initial value of isValidEmail as false in the useState aboveand this should make the rendering part work not only on the first time
The issue is that when you are sending data to the NotifyUser the first time when its state,
isValidEmail
isundefined
. So, when it becomes truthy the component NotifyUser gets loaded, hence mounted.Now the second time, when you change the state of
isValidEmail
or make a click it doesn’t show because the NotifyUser component is already loaded(mounted) but this time the component receives the new props but you are not hooking it to the useEffect here to perform a state update so the update doesn’t happen.To fix this you can make use of either of the two approaches, although I would prefer the second one since it minimises the changes to only its own component and doesn’t affect both the components, unlike first.
Approach 1 :
reset the isValidEmail back to null/undefined (always use null instead of undefined here and in initial state). Doing this after the timeout the component will get unmounted and then the state change will be taking place. The trick is component mounting and re-mounting, just so if its not clear in this approach manually.
Approach 2 :
just add the props inside the useEffect of the NotifyUser, which will make sure to re-run the