[英]React Hooks: How do I properly set up useEffect to handle changes to the state of a field in a form?
我正在嘗試創建一個通用表單組件來處理登錄案例、注冊案例等。我在登錄案例中大聲笑,我注意到盡管usernameError
state 達到 false 即用戶繼續輸入什么是實際的email,錯誤信息會一直存在:
我正在使用指示性進行驗證,但問題出在我的組件上,我認為因為錯誤的 state 正在實時變化,這就是問題所在。 但我不確定如何將useEffect
連接到我的onChange
處理程序。
這是我的組件:
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);
所以總結一下,我如何讓useEffect
監聽userNameError
和passwordError
的錯誤狀態的變化,因為我認為這是問題所在。
更新:
這是我認為 Iarz 的意思的演示。
useEffect(() => {
if (usernameError) {
return usernameError;
}
if (passwordError) {
return passwordError;
}
}, [usernameError, passwordError]);
useEffect
的第二個參數是一系列要觀察的東西,因此它知道何時觸發。 對於您當前的空數組,它僅在安裝時觸發(如果您包含返回,則會在卸載時觸發)。 你希望它什么時候開火? 嘗試將其更改為[passwordError, userNameError]
。
雖然您可以通過在useEffect
中使用依賴數組來跟蹤輸入的變化,但即使輸入是原始的或鍵入的值是有效的,出現錯誤 ui(紅色背景)也可能很煩人。
為什么不在這里驗證表單onSubmit
並避免useEffect
呢? Imo 這是使用 Semantic UI React 驗證表單的更好方法。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.