How to send User to Next Page After form validation in react?

不想你离开。 提交于 2020-07-09 12:35:10

问题


This in My SignUp Component, Im trying To send User to Signin Component If Username And Password Is correct.

this is Signup Code Below,

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;

Its Works Perfect If I Put Right username and password but in wrong username / password its also send me to Signin Page and Shows warning in console like this

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)

i wrap Both Component SignUp And Signin In Router,

this is my server.js file to send data if username and password is correct in database

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');
      }
    }
  );
});

回答1:


Your validForm makes an async call. By the time the async call is finished the validForm function as well as handleSubmit function execution is already completed. Then the then block is executed where you are setting state and therefore the error.

Solution: Make validForm an async function and await for your async call. Also make handleSubmit function an async and await for validForm.

Working demo

Code snippet

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>
    );
  }
}



回答2:


The issue could be on the handling of the response of the fetch. This is just a quick guess but try to not set the state of dataError and just modify the value of your variable dataError that you declared in this local function instead of the class variable. Does that make sense? when you check in your "if (nameError || passError || dataError)" you are checking for the local variable of your function and not the class which I think is fine but you aren't changing the variable if the response is an error. Second if you change the setState and then check the state.dataError you might not get the updated value refresh yet in the function.

Let me know if that makes sense and if it works.



来源:https://stackoverflow.com/questions/62737500/how-to-send-user-to-next-page-after-form-validation-in-react

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!