I have this code to log the users in. Currently, when I hit login, the button remains active. What I want is to disable the button when login is clicked and the current request is in progress. I tried using state that is initially false, and when I click the button it becomes true. And when the loading is done it becomes false again. But it didn't really work or maybe I did it in the wrong way.
Here is the code:
import api from '../services/api'
import { useState } from 'react'
import { Link, useNavigate } from 'react-router-dom'
import { validateFormDataForLogin } from '../validate'
export default function LoginPage() {
// form state
const [formData, setFormData] = useState({
'email': '',
'password': '',
})
// using navigate
const navigate = useNavigate()
// function to handle the changes
function handleChange(e) {
// getting the required values
const { name, value } = e.target
// setting the state
setFormData(prevFormData => ({
...prevFormData,
[name]: value,
}))
}
// function to handle the submit
async function handleSubmit(e) {
// preventing page reload
e.preventDefault()
// validating the data
const errorMessage = validateFormDataForLogin(formData)
// if there is an error message then show that error message
if (errorMessage) {
alert(errorMessage)
return
}
// if there is no error message then try to login the user
try {
// making a request for login
await api.post('/api/user/login', {
email: formData.email,
password: formData.password,
})
// redirect the user to the dashboard once logged in
navigate('/dashboard', {
replace: true, // so that when we hit back, we don't go to the login page again, and goes to the page before login
})
} catch (error) {
// alerting the error
if (error.response) {
alert(error.response.data.message)
}
}
}
return (
<div className='login'>
<h1 className='login--title'>Login</h1>
<div className='login--content'>
<form className='login--form' onSubmit={handleSubmit}>
<input type='text' className='login--form--input' placeholder='Email address' name='email' value={formData.email} onChange={handleChange} />
<input type='password' className='login--form--input' placeholder='Password' name='password' value={formData.password} onChange={handleChange} />
<p className='login--form--forgot_password'>Forgot Password</p>
<input className='login--form--submit' type='submit' value='LOGIN' />
</form>
<div className='login--row'>
<span className='login--row--text'>Don't have an account?</span>
<Link to='/register' className='login--row--link'>Register</Link>
</div>
</div>
</div>
)
}
Any help will be greatly appreciated.
CodePudding user response:
You can keep track of loading state in a separate state :
const [isLoading, setIsLoading] = useState(false)
async function handleSubmit(e) {
setIsLoading(true)
/* ... */
try {
// making a request for login
await api.post('/api/user/login', {
email: formData.email,
password: formData.password,
})
setIsLoading(false)
/* ... */
} catch (error) {
setIsLoading(false)
/* ... */
}
}
Then, disable the submit button if isLoading
is true :
<input type="submit" disabled={isLoading} />
CodePudding user response:
Psuedo code
You can use a state variable to store disable / enable of the button. default is false. lets say variable is
isDisabled
. Likeconst [isDisabled, setIsDisabled] = useState(false)
Use that variable in conditional validation on the button like
<input className='login--form--submit' type='submit' value='LOGIN' disabled={isDisabled}
You need to keep the state of the variable updated while making your API request / on success or on failure