I am trying to create a generic form component to take in a Login case, Registration case etc. I am on the Login case lol and I've noticed despite the usernameError
state reaching false ie a user has gone on to enter what is a actual email, the error message will persist:
I am using Indicative to do the validation, but the problem is with my component, I would think because the state for the errors is changing in real time that is the problem. But I am not sure how I would connect useEffect
to my onChange
handler.
Here is my component:
import React, { useState, useEffect } from 'react';
import {
Loader,
Dimmer,
Transition,
Button,
Form,
Grid,
Header,
Message,
Segment
} from 'semantic-ui-react';
import axios from 'axios';
import {
logInUser,
userHasBeenVerified,
userHasNotBeenVerified,
resetCountNotVerified
} from '../../store/reducers/users/index';
import { Link } from 'react-router-dom';
import { validateInputs } from '../../utils/index';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
function FormComponent({
formType,
match,
isLoggedIn,
accountVerified,
userHasBeenVerified,
resetCountNotVerified
}) {
function isLoginForm() {
console.log('formType; ', formType);
return (
<div className="login-form">
{' '}
{}
<style>
{`body > div, body > div > div, body > div > div > div.login-form { height: 100%;}`}{' '}
</style>
<Grid textAlign="center" style={{ height: '100%' }} verticalAlign="middle">
<Grid.Column style={{ maxWidth: 450 }}>
<Header as="h2" color="green" textAlign="center">
Log-in to your account
</Header>
{console.log('usernameError ', usernameError)};
<Form
size="large"
onSubmit={e => handleSubmit(e, formType)}
error={formError}
>
<Segment stacked>
<Form.Input
fluid
icon="user"
iconPosition="left"
placeholder="E-mail address, e.g. joe@schmoe.com"
name="username"
value={username}
onChange={e => handleChange(e)}
error={usernameError}
/>
<Transition visible={usernameError} animation="scale" duration={duration}>
<Message error content={usernameFeedback} />
</Transition>
<Form.Input
fluid
icon="lock"
iconPosition="left"
placeholder="Password"
name="password"
type="password"
value={password}
onChange={e => handleChange(e)}
error={passwordError}
/>
<Transition visible={passwordError} animation="scale" duration={duration}>
<Message error content={passwordFeedback} />
</Transition>
<Button color="green" fluid size="large" disabled={disableButton}>
Log-in
</Button>
<br />
<Link to="/forgot_password">Forgot password?</Link>
<Transition
visible={accountVerified === false ? true : false}
unmountOnHide={true}
animation="scale"
duration={duration}
>
{isLoading ? (
<Dimmer active inverted>
<Loader />
</Dimmer>
) : (
<Message
color="yellow"
centered="true"
header={responseMessage[0]}
content={responseMessage[1]}
/>
)}
</Transition>
<Transition
visible={formError}
unmountOnHide={true}
animation="scale"
duration={duration}
>
{isLoading ? (
<Dimmer active inverted>
<Loader />
</Dimmer>
) : (
<Message
error
centered="true"
header={responseMessage[0]}
content={responseMessage[1]}
/>
)}
</Transition>
<Transition
visible={formSuccess}
unmountOnHide={true}
animation="scale"
duration={duration}
>
{isLoading ? (
<Dimmer active inverted>
<Loader />
</Dimmer>
) : (
<Message
success
header={responseMessage[0]}
content={responseMessage[1]}
/>
)}
</Transition>
</Segment>
</Form>
{formError ? (
<Transition visible={formError} animation="scale" duration={1000}>
{isLoading ? (
<Dimmer active inverted>
<Loader />
</Dimmer>
) : (
<Message>
<Link to="/register">Register</Link>{' '}
</Message>
)}
</Transition>
) : null}
</Grid.Column>{' '}
</Grid>{' '}
</div>
);
}
function loginSubmit() {
axios
.post('http://localhost:8016/users/login', {
username: username,
password: password
})
.then(response => {
console.log('response', response);
if (response.status === 200) {
userHasBeenVerified();
setTimeout(() => {
logInUser();
history.push('/profile');
}, 5000);
setUsername('');
setPassword('');
setFormError(false);
setFormSuccess(true);
setIsLoading(false);
setResponseMessage(response.data.msg);
}
})
.catch(function(error) {
if (error.response) {
if (error.response.status === 401) {
userHasNotBeenVerified();
setUsername('');
setPassword('');
setFormError(false);
setFormSuccess(true);
setIsLoading(false);
setResponseMessage(error.response.data.msg);
}
if (error.response.status === 404) {
resetCountNotVerified();
setUsername('');
setPassword('');
setFormError(true);
setFormSuccess(false);
setIsLoading(false);
setResponseMessage(error.response.data.msg);
}
console.log('error.response.data', error.response.data);
console.log('error.response.headers', error.response.headers);
}
});
}
var Forms = {
Login: [isLoginForm, loginSubmit],
}
var [fadeUp, setFadeUp] = useState('fade up');
var [duration, setDuration] = useState(500);
var [name, setName] = useState('');
var [username, setUsername] = useState('');
var [usernameFeedback, setUsernameFeedback] = useState('');
var [usernameError, setUsernameError] = useState(false);
var [userNameDup, setUserNameDup] = useState(false);
var [password, setPassword] = useState('');
var [passwordFeedback, setPasswordFeedback] = useState('');
var [passwordError, setPasswordError] = useState(false);
var [password_confirmation, setPasswordConfirmation] = useState('');
var [passwordConfirmationError, setPasswordConfirmationError] = useState(false);
var [passwordConfirmationFeedback, setPasswordConfirmationFeedback] = useState('');
var [formSuccess, setFormSuccess] = useState(false);
var [formError, setFormError] = useState(false);
var [disableButton, setDisableButton] = useState(true);
var [isLoading, setIsLoading] = useState(false);
var [responseMessage, setResponseMessage] = useState({});
var [tokenExpired, setTokenExpired] = useState(false);
var [responseCodeSuccess, setResponseCodeSuccess] = useState(false);
var [error, setError] = useState(false);
useEffect(() => { /* Not sure what to do here */
setUsernameError();
setPassword();
// }, []);
function handleChange(e) {
console.log('e ', e);
e.persist();
if (e.target.name === 'username') {
console.log('username', e.target.name);
setUsername(e.target.value);
}
if (e.target.name === 'password') {
console.log('password', e.target.name);
setPassword(e.target.value);
}
validateInputs(
formType,
username,
setUsernameError,
setUsernameFeedback,
password,
setPasswordError,
setPasswordFeedback,
setDisableButton
);
}
function handleSubmit(event, formType) {
event.preventDefault();
return Forms[formType][1]();
}
console.log('formType; ', formType);
return Forms[formType][0]();
}
function mapStateToProps(state) {
const { users } = state;
const { accountVerified, isLoggedIn } = users;
return { accountVerified, isLoggedIn };
}
const mapDispatchToProps = dispatch =>
bindActionCreators(
{ logInUser, userHasBeenVerified, userHasNotBeenVerified, resetCountNotVerified },
dispatch
);
export default connect(
mapStateToProps,
mapDispatchToProps
)(FormComponent);
So to sum it up how do I have useEffect
listen for the the changes to the error states for userNameError
and passwordError
as I believe that is the problem.
Update:
This is a demo of what I thought Iarz meant..
useEffect(() => {
if (usernameError) {
return usernameError;
}
if (passwordError) {
return passwordError;
}
}, [usernameError, passwordError]);
The second argument for useEffect
is an array of things to watch so it knows when to fire. With your current empty array, it only fires on mount (and if you included a return, that would fire on unMount). When do you want it to fire? Try changing that to [passwordError, userNameError]
.
While you can track changes in inputs by using dependency array in useEffect
, it might be annoying to have error ui (red backgrounds) even if input is pristine or typed value is valid.
Why not validate form onSubmit
and avoid useEffect
here? Imo that's better way to validate form with Semantic UI React.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.