hello guys pls i have a challenge in my react app, i am trying to enable multiple choice login where a user can either use his mail or even hi username to login. i got it working from my server using postman but when i try it on my frontend it doesnt allow me to use multiple refs on it, i am only allowed to use either the username or email. Here is my code
function Login() {
const password = useRef();
const email = useRef();
const username = useRef();
const { isFetching, dispatch } = useContext(AuthContext);
const handleClick = (e) => {
e.preventDefault();
try {
loginCall(
{
username: username.current.value,
email: email.current.value,
password: password.current.value,
},
dispatch
);
} catch (err) {
console.log(err.response);
}
};
return (
<>
<div className="log__bg">
<div className="login">
<div className="loginWrapper">
<div className="loginLeft">
<span className="loginDesc">Welcome Back</span>
<ToastContainer />
</div>
<div className="loginRight">
<form className="loginBox" onSubmit={handleClick} >
<input
placeholder="Email, phone, or username"
type="text"
required
className="loginInput"
ref={username}
/>
<input
placeholder="Password"
type="password"
required
minLength="6"
className="loginInput"
ref={password}
/>
<button
className="loginButton"
type="submit"
disabled={isFetching}
>
{isFetching ? (
<CircularProgress color="white" size="20px" />
) : (
"Log In"
)}
</button>
<Link id="auth_route" to="/register">
<button className="loginRegButton">
{isFetching ? (
<CircularProgress color="white" size="20px" />
) : (
"Create a New Account"
)}
</button>
</Link>
<div className="forgot__password">
<Link className="forgot__password__btn" to="/forgot-password">
Forgot Password?
</Link>
</div>
</form>
</div>
</div>
</div>
</div>
</>
);
}
export default Login;
CodePudding user response:
Why you need 2 refs ? user will provide username or email in the same input field. Use just one ref than you can have a logic or regex in your backend to detect if the provided value is an email or a username:
const handleClick = (e) => {
e.preventDefault();
let username = null
let email = null
const emailRegex = /^\S @\S \.\S $/
const inputValue = username.current.value
if(inputValue.match(emailRegex)){
email = inputValue
} else {
username = inputValue
}
try {
loginCall(
{
username: username,
email: email,
password: password.current.value,
},
dispatch
);
} catch (err) {
console.log(err.response);
}
};
With this if the user provided an email, username will be sent as null to the server and vice versa. Then you can check on the server if you get an email or a username.
UPDATE: You can also just use a state and don't use ref at all:
const [usernameValue, setUsernameValue]=React.useState("")
const [passwordValue, setPasswordValue]=React.useState("")
const handleClick = (e) => {
e.preventDefault();
let username = null
let email = null
const emailRegex = /^\S @\S \.\S $/
if(usernameValue.match(emailRegex)){
email = inputValue
} else {
username = inputValue
}
try {
loginCall(
{
username: username,
email: email,
password: passwordValue,
},
dispatch
);
} catch (err) {
console.log(err.response);
}
};
return (
...
<form className="loginBox" onSubmit={handleClick} >
<input
placeholder="Email, phone, or username"
type="text"
required
className="loginInput"
value={usernameValue}
onChange={e=>setUsernameValue(e.target.value)}
/>
<input
placeholder="Password"
type="password"
required
minLength="6"
className="loginInput"
value={passwordValue}
onChange={e=>setPasswordValue(e.target.value)}
/>
...
...
)
CodePudding user response:
I agree with @PatersonCode, the best way would be to use React.useState
and just one variable to store your input value.
You didn't mention what error you're getting, but here's an example that I hope might help you in some way:
https://codesandbox.io/s/choose-login-method-example-xgpfue?file=/src/Login.js