I'm building registration form. I have signup.tsx
which has validation for inputs. But I ran into a problem, I want to disable the button if the inputs are empty and if the inputs have one or more error during registration. I have no idea how to disable button with disable={}
I'm trying to do like this: disable={!input}
. But of course it's not right
My code of signup.tsx
:
import React, { useState } from 'react';
import './signup.css';
function Signup() {
const [input, setInput] = useState({
username: "",
email: "",
password: ""
});
const [error, setError] = useState({
username: "",
email: "",
password: ""
});
const onInputChange = (e: any) => {
const { name, value } = e.target;
setInput(prev => ({
...prev,
[name]: value
}));
validateInput(e);
};
const validateInput = (e: any) => {
let { name, value } = e.target;
setError(prev => {
const stateObj = { ...prev, [name]: "" };
const minLengthUser = /.{4,}/;
const minLengthUsername = minLengthUser.test(value);
const minLenghtPass = /.{6,}/;
const minLenghtPassword = minLenghtPass.test(value);
switch (name) {
case "username":
if (!value) {
stateObj[name as keyof typeof stateObj] = "Username is required";
} else if (!minLengthUsername) {
stateObj[name as keyof typeof stateObj] = "Username should be minimum 4 characters"
};
break;
case "email":
if (!value) {
stateObj[name as keyof typeof stateObj] = "Email address is required"
} else if (!/^[A-Z0-9._% -] @[A-Z0-9.-] \.[A-Z]{2,4}$/i.test(input.email)) {
stateObj[name as keyof typeof stateObj] = 'Invalid email address'
}
break;
case "password":
if (!value) {
stateObj[name as keyof typeof stateObj] = "Password is required";
} else if (!minLenghtPassword) {
stateObj[name as keyof typeof stateObj] = "Password should be minimum 6 characters";
}
break;
default:
break;
}
return stateObj;
});
}
return (
<div className="container">
<div className="box">
<h1>
<p className="title">Create an account</p>
</h1>
<form className="form">
<div className="form-outline">
<label className="input-label">Your Name</label>
<input
name="username"
type="text"
className="input"
value={input.username}
onChange={onInputChange}
onBlur={validateInput}
/>
{error.username && <div className="alert"><span className="err">{error.username}</span></div>}
</div>
<div className="form-outline">
<label className="input-label">Your Email</label>
<input
name="email"
type="email"
className="input"
value={input.email}
onChange={onInputChange}
onBlur={validateInput}
/>
{error.email && <div className="alert"><span className="err">{error.email}</span></div>}
</div>
<div className="form-outline">
<label className="input-label">Password</label>
<input
name="password"
type="password"
className="input"
value={input.password}
onChange={onInputChange}
onBlur={validateInput}
/>
{error.password && <div className="alert"><span className='err'>{error.password}</span></div>}
</div>
<div className="button">
<button className="btn">Create account</button>
</div>
</form>
</div>
</div>
)
}
export default Signup;
CodePudding user response:
You could create a method isInputValid
which returns a boolean. It loops over the error object checking errors if they're not the default value ""
return false. If they all are the default return true.
const isInputValid = Object.values(error).reduce((isValid: boolean, err) => {
if (err !== "") return false;
// will return true if isValid is true else returns false
return isValid && true;
}, true);
Which you can use like this
<button className="btn" disabled={!isInputValid}>
Create account
</button>
EDIT:
To disable the button at the start, you can use null
as a value.
type ErrorType = {
username: string | null;
email: string | null;
password: string | null;
};
const [error, setError] = useState<ErrorType>({
username: null,
email: null,
password: null,
});
const isValid = Object.values(error).reduce((isValid: boolean, error) => {
if (error === null || error !== "") return false;
return isValid && true;
}, true);