首页 > 解决方案 > 三次失败登录尝试重定向的计数器不执行任何操作

问题描述

我正在尝试在我的 React 应用程序中创建一个计数器,如果服务器(Expressjs)在 pin 上发送状态为 false 尝试 3 次,则重定向,我已经通过控制台日志验证了状态实际上已发送,它在 chrome 控制台中可见. 但由于某种原因,我的应用程序没有重定向。我正在尝试this.props.history.push在我的 React 返回中重定向使用和条件渲染。要计算我tries在构造函数中定义的尝试次数,并为每次失败的尝试增加 1,如果该值大于 3,我想重定向到不同的页面。这是我的反应前端代码(我删除了导入):

class logIn extends React.Component {
  constructor() {
    super();
    this.state = {
      cardnumber: '',
      pin: '',
      servercardnumber: {
        message: '',
        status: '',
        tries: 0
      }
    };

    this.handleSubmit = this.handleSubmit.bind(this);
  }
  handleEvent = e => {
    this.setState({ [e.target.name]: e.target.value });
  };
  handleSubmit = async e => {
    e.preventDefault();
    // get our form data out of state
    const { cardnumber, pin } = this.state;
    const data = { cardnumber, pin };
    const url = '/api/login';
    const serverResponse = await fetch(url, {
      method: 'POST',
      headers: {
        Accept: 'application/json',
        'Content-Type': 'application/json',
        'Access-Control-Allow-Origin': '*',
        'Access-Control-Allow-Credentials': true
      },
      body: JSON.stringify(data)
    });
    const json = await serverResponse.json();
    console.log(json);
    console.log('json status is: ', json.status);
    if (json.status === false) {
      this.state.tries++;
    }
    if (this.state.tries < 3) {
      this.state.tries = false;
      this.props.history.push('/selectaction');
    }

    this.setState(
      prevState => {
        sessionStorage.setItem('cardnumber', json.message);

        console.log('json status is: ', json.status);
        return {
          servercardnumber: json.message,
          status: json.status
        };
      },
      () => {
        console.log(this.state.cardnumber);
      }
    );
  };

  render() {
    const { cardnumber, pin, status, tries } = this.state;
    return (
      <React.Fragment>
        {tries ? !<Redirect to="/selectaction" /> : null}
        {console.log('server says:')}
        {console.log(status)}
        <CssBaseline /> {/*https://material-ui.com/style/css-baseline */}
        <h1> Log in</h1>
        <form onSubmit={this.handleSubmit} method="POST" action="/api/formdata">
          <br />
          {/* Bytt ut med CSS block elementer eller noe slikt, bytt name på form fields til å hentes via JS  */}
          <TextField
            required
            id="standard-required"
            label="Card number"
            className="tekstfelt"
            margin="normal"
            defaultValue={cardnumber}
            name="cardnumber"
            onInput={e => {
              e.target.value = Math.max(0, parseInt(e.target.value))
                .toString()
                .slice(0, 12);
            }}
            onChange={e => this.handleEvent(e)}
          />
          <br />
          <TextField
            required
            id="standard-required"
            label="PIN code"
            className="tekstfelt"
            margin="normal"
            type="password"
            defaultValue={pin}
            name="pin"
            onInput={e => {
              e.target.value = Math.max(0, parseInt(e.target.value))
                .toString()
                .slice(0, 4);
            }}
            onChange={e => this.handleEvent(e)}
          />
          <br />
          <br />
          <Button type="submit" variant="contained" color="primary" className="test">
            <div className="test">Log in</div>
          </Button>
        </form>
        <p>
          Cardnumber: {this.state.cardnumber} <br />
          pin-code: {this.state.pin} <br />
        </p>
      </React.Fragment>
    );
  }
}
export default logIn;

有任何想法吗?

标签: javascriptreactjs

解决方案


首先,在您的初始状态中,tries键嵌套在servercardnumber键下,您尝试直接在状态上访问它。然后你增加它,所以:

a)你直接改变状态,你不应该

b)如果对象上不存在键并且您尝试增加它,您将获得NaN此键的值

所以在那个操作之后你现在有了this.state.tries,但设置为NaN永远不会小于3(我认为你的意思是'大于'这里),但即使是这样,你然后将trieskey 设置为 false (再次直接) - 在第二次尝试, 增加 false 将导致 0,因此您将在比您想要的更多尝试后被重定向。修复初始状态后:

  this.state = {
    tries: 0,
    cardnumber: '',
    pin: '',
    servercardnumber: {
      message: '',
      status: '',
    }
  };

和您的处理程序,为简洁起见省略了一些部分:

handleSubmit = async e => {
    const {tries} = this.state
    // ...
    if (json.status === false) {
      this.setState(prevState => ({tries: prevState.tries + 1}, () => {
        if (tries >= 3) {
          this.props.history.push('/selectaction');
          return
        }
      })
    }
    // ...
    );
  };

处理程序中改变了三件事——如果你想在 setState 中使用以前的状态,你应该传递一个函数。如果你想做一些依赖于首先改变状态的事情,你可以在作为第二个可选参数传递给 setState 的回调函数中做到这一点。最后你返回到结束执行函数(我假设如果 json.status 第三次为假,你不想做任何其他事情,只是重定向)


推荐阅读