React Hooks:如何正确设置useEffect来处理表单中字段状态的更改?

时间:2020-04-03 02:08:50

标签: reactjs validation react-hooks use-effect use-state

我正在尝试创建一个通用的表单组件来接受Login案例,Registration案例等。我在Login案例中大声笑,尽管usernameError状态变为false,即用户走了,但我注意到了继续输入什么是实际的电子邮件,错误消息将持续存在:

enter image description here

我正在使用Indicative进行验证,但是问题出在我的组件上,我想是因为错误的状态正在实时更改,这就是问题所在。但是我不确定如何将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应该如何监听userNameErrorpasswordError的错误状态的更改,因为我认为这是问题所在。

更新

这是我认为Iarz的意思的演示。

 useEffect(() => {
    if (usernameError) {
      return usernameError;
    }

    if (passwordError) {
      return passwordError;
    }
  }, [usernameError, passwordError]);

2 个答案:

答案 0 :(得分:1)

useEffect的第二个参数是一系列要观察的东西,因此它知道何时触发。对于当前的空数组,它仅在安装时触发(如果包含返回,则将在unMount上触发)。你什么时候要开火?尝试将其更改为[passwordError, userNameError]

答案 1 :(得分:1)

尽管您可以通过使用useEffect中的依赖项数组来跟踪输入的变化,但是即使输入是原始的或键入的值是有效的,也会出现错误ui(红色背景)的问题。

为什么不验证表单onSubmit并在这里避免使用useEffect? Imo是使用语义UI React验证表单的更好方法。