[英]React Hooks: How do I properly set up useEffect to handle changes to the state of a field in a form?
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:我正在尝试创建一个通用表单组件来处理登录案例、注册案例等。我在登录案例中大声笑,我注意到尽管usernameError
state 达到 false 即用户继续输入什么是实际的email,错误信息会一直存在:
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.我正在使用指示性进行验证,但问题出在我的组件上,我认为因为错误的 state 正在实时变化,这就是问题所在。 But I am not sure how I would connect useEffect
to my onChange
handler.但我不确定如何将useEffect
连接到我的onChange
处理程序。
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.所以总结一下,我如何让useEffect
监听userNameError
和passwordError
的错误状态的变化,因为我认为这是问题所在。
Update:更新:
This is a demo of what I thought Iarz meant..这是我认为 Iarz 的意思的演示。
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. useEffect
的第二个参数是一系列要观察的东西,因此它知道何时触发。 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]
.尝试将其更改为[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.虽然您可以通过在useEffect
中使用依赖数组来跟踪输入的变化,但即使输入是原始的或键入的值是有效的,出现错误 ui(红色背景)也可能很烦人。
Why not validate form onSubmit
and avoid useEffect
here?为什么不在这里验证表单onSubmit
并避免useEffect
呢? Imo that's better way to validate form with Semantic UI React. Imo 这是使用 Semantic UI React 验证表单的更好方法。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.