简体   繁体   English

React Hooks:如何正确设置 useEffect 以处理对表单中字段的 state 的更改?

[英]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监听userNameErrorpasswordError的错误状态的变化,因为我认为这是问题所在。

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.

相关问题 如何将它变成 React Hooks for useEffect()? - How do I turn this into React Hooks for useEffect()? 如何使用 useEffect 正确设置 API 调用? - How do I properly set up an API call using useEffect? 我如何正确使用 useEffect 进行异步获取调用和反应? 反应钩子/详尽的deps - How do i properly use useEffect for a async fetch call with react? react-hooks/exhaustive-deps React 无法在 useEffect() 中使用钩子设置状态 - React can't set state with hooks in useEffect() React hooks - 当 state 更改为相同的值时,如何强制 useEffect 运行? - React hooks - how to force useEffect to run when state changes to the same value? 如何使用 React Hooks 和 Context API 将来自 useEffect 内部调用的多个端点的数据正确添加到状态对象? - How do I correctly add data from multiple endpoints called inside useEffect to the state object using React Hooks and Context API? 如何在 React 的 useEffect 中设置状态? - How to set the state in useEffect in React? 你如何使用 React Hooks 处理外部 state? - How do you handle external state with React Hooks? 如何正确设置我的 useEffect,以免收到缺少依赖项警告? - How do I properly set up my useEffect so I don't receive a missing dependency warning? 使用钩子时如何重新渲染表单值和状态值,并且在不同的组件中更改状态 - How do I rerender form value and state value when using hooks and state is changed in a different component in react
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM