I have developed a React+NextJS application. The login page on load uses a useEffect
hook to ask my server if the admin account exists. This in turn sets a hook, which affects what content is loaded.
const [adminExists, setAdminExists] = useState(false); // <- assume account does not exist
const [submitEnabled, setSubmitEnabled] = useState(false);
const [errors, setErrors] = useState("");
useEffect(() => {
... request from server
setAdminExists(true/false)
})
Then the return function of the page:
const LoginForm = () => {
if (adminExists) {
return (...loginForm)
} else {
return (
<div ...props>
<h1>title</h1>
<Form ...props>
<div ...props>
<Input ...props/> // <- username
</div>
<div ...props>
<Input ...props/> // <- password
</div>
<div ...props>
<Input ...props/> // <- password confirm
</div>
<div ...props>
<Button ...props isDisabled={!submitEnabled}/> // <- submit button
</div>
<div ...props>
{errors}
</div>
</Form>
</div>
)
}
}
return (
<LoginForm/>
)
The Input
boxes have a key up listener as follows:
onKeyUp={validatePasswords}
And validatePasswords
:
const validatePasswords = (e) => {
// extract form data
const password = form.get('password')
const passwordConfirm = form.get('passwordConfirm')
setSubmitEnabled(password.length > 0 && passwordConfirm > 0 && password === passwordConfirm)
if (!password.startsWith(passwordConfirm)) {
setErrors("Passwords must match")
} else {
setErrors("") // <- clear errors
}
}
The problem:
startsWith
check is true, nothing happens (as expected)startsWith
check, the input boxes clear. The error appears for a split second and disappears.I believe the parent component is re-rendering when the hook is changed or am I wrong?
How do I get this to work? I am not very experienced with React or NextJS so help is much appreciated.
Ok so I was playing around and it seems the issue is in the LoginForm
const. It just doesn't like the fact its being returned from a call. I really don't understand why, perhaps someone with more understanding could explain?
However, I fixed the input box issue by moving the form into the main return of the component.
So, instead of:
const LoginForm = () => {
if (adminExists) return someComponent;
else return someOtherComponent
}
return (
<LoginForm/>
)
I now do:
if (adminExists) return (
<div ...props>
... the login form and the rest
</div>
)
else return (
<div ...props>
...the signup form and the rest
</div>
)
This stopped the entire page re-rendering on every value entered into an input box.