仅在道具更新后如何运行onSubmit = {}?

时间:2019-04-22 11:47:39

标签: javascript reactjs firebase redux firebase-authentication

仅在从reducer更新收到我的道具后,我才想在表单上运行onSubmit。

const mapStateToProps = state => {
  return {
    authError: state.auth.authError  // I want this to update before the action.
  };
};

如果我在onSutmit处理程序中console.log authError,我会收到旧的authError。第二次运行它时,我收到更新的authError。

  handleSubmit = e => {
    e.preventDefault();
    console.log("error exists?", this.props.authError);
    this.props.signIn(this.state); //dispatches a login action
    this.handleHideLogin(); // hides the form after action is dispatched
};

我只想在分派动作且错误为null后才隐藏表单。 (如果身份验证成功,它将自动返回null)

我尝试使用setTimeout()并在技术上可行,但是我想知道是否还有更“适当”的方法来实现它。

handleSubmit = e => {
    e.preventDefault();
    this.props.signIn(this.state);

     setTimeout(() => {
       if (this.props.authError) {
         console.log("returns error =>", this.props.authError);
       } else {
         console.log("no error =>", this.props.authError);
         this.handleHideLogin();
       }
     }, 500);
  };

我组件的一部分供参考

<form onSubmit={!this.props.authError ? this.handleSubmit : null}> 
   //the above onSubmit is different if I use the setTimeout method.
          <div className="modal-login-body">
            <div className="modal-login-input">
              <input
                type="email/text"
                name="email"
                autoComplete="off"
                onChange={this.handleChange}
                required
              />
              <label htmlFor="email" className="label-name">
                <span className="content-name">EMAIL</span>
              </label>
            </div>
            <div className="modal-login-input">
              <input
                type="password"
                name="password"
                autoComplete="off"
                onChange={this.handleChange}
                required
              />
              <label htmlFor="password" className="label-name">
                <span className="content-name">PASSWORD</span>
              </label>
            </div>
          </div>
          <div className="my-modal-footer">
            <p className="login-failed-msg">
              {this.props.authError ? this.props.authError : null}
            </p>
            <button type="submit" className="complete-login-button">
              LOGIN
            </button>
            <a href="CHANGE" className="forgot-password">
              <u>Forgot your password?</u>
            </a>
          </div>
        </form>

2 个答案:

答案 0 :(得分:1)

我假设this.props.signIn是一个异步函数。 因此this.props.authError是异步更新的,这就是为什么如果设置超时在某些情况下会起作用的原因(当您得到的响应时间少于5秒时)。

解决此问题的一种方法是使用thencatch而不更新表单状态

handleSubmit = e => {
    e.preventDefault();
    this.props.signIn(this.state).then(resp => {
        this.setState({userIsValid: true, failure: null})
        this.onUpdate(userIsValid);
    })
    .catch(err => {
       this.setState({userIsValid: false, failure: "Failed to login"})
    });
}

并使用if-else确定是显示表单还是显示您的网站

class App extends React.Component {
  render() {
    if (this.state.isValidUser) {
      return <Main />
    } else {
      return <LoginForm onUpdate={(isValid) => {this.setState({isValidUser: isValid})} />
    }
  }
}

换句话说,LoginForm组件存储用户名,密码,失败(登录失败的错误消息)和isValidUser(确定登录是否成功)。 该应用程序具有确定要显示的内容,网站或登录组件的状态。使用作为道具传递到登录组件的onUpdate,我们可以更新App的状态并显示登录成功的网站。

希望对您有帮助。

答案 1 :(得分:0)

我通过在整个组件上进行条件渲染来解决了这个问题。 如果我登录,我使用了从react-router-dom重定向来仅不呈现该元素。

如果我已经登录,则无论如何都不需要显示登录表单。

   if (this.props.loggedOut) {
      <form onSubmit={this.handleSubmit}>
        //...
      </form>
    } else {
      return <Redirect to="/" />;
    }