表单验证后如何将用户发送到下一页以进行react?

IT技术 node.js reactjs express react-router-dom
2021-05-09 17:30:34

这在我的注册组件中,如果用户名和密码正确,我会尝试将用户发送到登录组件。

这是下面的注册码,

import React, { Component } from 'react';
import { Link } from 'react-router-dom';
import Axios from 'axios';

const initianValue = {
  username: '',
  password: '',
  nameError: '',
  passError: '',
  dataError: '',
};

class SignUp extends Component {
  constructor(props) {
    super(props);
    this.state = initianValue;
    this.handleInputChange = this.handleInputChange.bind(this);
    this.handleSubmit = this.handleSubmit.bind(this);
  }

  handleInputChange = (e) => {
    this.setState({
      [e.target.name]: e.target.value,
    });
  };

  validForm() {
    let nameError = '';
    let passError = '';
    let dataError = '';

    const user = {
      username: this.state.username,
      password: this.state.password,
    };

    if (!this.state.username) {
      nameError = 'Enter Name';
    }

    if (user.username !== '' && user.password !== '') {
      Axios.post('http://localhost:9000/checkUser', user)
        .then((res) => this.setState({ dataError: res.data }))
        .catch((err) => console.log(err));
    }

    if (!this.state.password) {
      passError = 'Enter Password';
    }

    if (nameError || passError || dataError) {
      this.setState({
        nameError,
        passError,
        dataError,
      });
      return false;
    }

    return true;
  }

  handleSubmit = (e) => {
    e.preventDefault();
    const isvalid = this.validForm();
    if (isvalid) {
      this.setState(initianValue, () => this.props.history.push('/SignIn'));
    }
  };

  render() {
    return (
      <div className='Main'>
        <span className='create'>Create Account</span>
        <div className='SignUp'>
          <form onSubmit={this.handleSubmit}>
            <div className='form-group'>
              <label>Username</label>
              <input
                type='text'
                name='username'
                value={this.state.username}
                className='form-control'
                onChange={this.handleInputChange}
              />
              <div className='error'>
                {this.state.nameError}
                {this.state.dataError}
              </div>
              <br />
              <label>Password</label>
              <input
                type='password'
                name='password'
                value={this.state.password}
                className='form-control'
                onChange={this.handleInputChange}
              />
              <div className='error'>{this.state.passError}</div>
              <br />

              <button type='submit' className='btn btn-primary'>
                Sign Up
              </button>
            </div>
          </form>
        </div>
        <div className='signinForm'>
          <label>
            Already Have Account <Link to='/Signin'> Sign In </Link>
          </label>
        </div>
      </div>
    );
  }
}

export default SignUp;

如果我输入正确的用户名和密码但输入错误的用户名/密码,它的工作原理很完美,它也会将我发送到登录页面并像这样在控制台中显示警告

index.js:1 Warning: Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in the componentWillUnmount method.
    in SignUp (created by Context.Consumer)

我包装了组件注册和登录路由器,

这是我的 server.js 文件,如果数据库中的用户名和密码正确,将发送数据

app.post('/checkUser', function (req, res) {
  const name = req.body.username;
  const pass = req.body.password;

  conn.query(
    `SELECT * FROM users WHERE username  = (?) AND password = (?) `,
    [name, pass],
    (err, rows) => {
      if (err) throw err;

      if (!rows.length) {
        res.send('Wrong Data');
      }
    }
  );
});
2个回答

validForm进行异步调用。到异步调用完成时,validForm函数以及handleSubmit函数执行已经完成。然后then在您设置状态的地方执行块,因此会出现错误。

解决方案:创建validForm一个异步函数并等待您的异步调用。也使handleSubmit函数 async 和 await for validForm

工作演示

代码片段

class SignUp extends Component {
  constructor(props) {
    super(props);
    this.state = initianValue;
    this.handleInputChange = this.handleInputChange.bind(this);
    this.handleSubmit = this.handleSubmit.bind(this);
  }

  handleInputChange = e => {
    this.setState({
      [e.target.name]: e.target.value
    });
  };

  async validForm() {
    let nameError = "";
    let passError = "";
    let dataError = "";

    const user = {
      username: this.state.username,
      password: this.state.password
    };

    if (!this.state.username) {
      nameError = "Enter Name";
    }

    if (user.username !== "" && user.password !== "") {
      await Axios.get("https://jsonplaceholder.typicode.com/todos/1", user) //fake api
        .then(res => {
          dataError = "user already exists"; //provide dynamic error..
          //this.setState({ dataError: res.data }); // not required
        })
        .catch(err => console.log("err", err));
    }

    if (!this.state.password) {
      passError = "Enter Password";
    }

    if (nameError || passError || dataError) {
      this.setState({
        nameError,
        passError,
        dataError
      });
      return false;
    }

    return true;
  }

  handleSubmit = async e => {
    e.preventDefault();
    const isvalid = await this.validForm();
    if (isvalid) {
      this.setState(initianValue, () => this.props.history.push("/SignIn"));
    }
  };

  render() {
    return (
      <div className="Main">
        <span className="create">Create Account</span>
        <div className="SignUp">
          <form onSubmit={this.handleSubmit}>
            <div className="form-group">
              <label>Username</label>
              <input
                type="text"
                name="username"
                value={this.state.username}
                className="form-control"
                onChange={this.handleInputChange}
              />
              <div className="error">
                {this.state.nameError}
                {this.state.dataError}
              </div>
              <br />
              <label>Password</label>
              <input
                type="password"
                name="password"
                value={this.state.password}
                className="form-control"
                onChange={this.handleInputChange}
              />
              <div className="error">{this.state.passError}</div>
              <br />

              <button type="submit" className="btn btn-primary">
                Sign Up
              </button>
            </div>
          </form>
        </div>
        <div className="signinForm">
          <label>
            Already Have Account <Link to="/Signin"> Sign In </Link>
          </label>
        </div>
      </div>
    );
  }
}

问题可能出在获取响应的处理上。这只是一个快速的猜测,但尽量不要设置 dataError 的状态,而只是修改你在这个本地函数而不是类变量中声明的变量 dataError 的值。那有意义吗?当您签入“if (nameError || passError || dataError)”时,您正在检查函数的局部变量,而不是我认为很好的类,但如果响应是错误,则不会更改变量. 其次,如果您更改 setState 然后检查 state.dataError 您可能还没有在函数中获得更新的值刷新。

让我知道这是否有意义以及它是否有效。