0

I would like to prevent a react-router transition away from a form if it is invalid. Using a prompt to do this is unsatisfactory, as I want to totally block the user from navigating to a new route until the form is valid (whereas the prompt seems to always provide the user the option to proceed), and would like to display an error message on my page instead of an intrusive prompt.

How might I prevent this transition without a prompt?

My form:

    <form>
      <div>
        <label>Name: </label>
        <input
          type="text"
          name="name"
          id="name"
          onChange={this.handleChange}
          autoComplete="name"
        />
      </div>
      <div>
        <label>Email: </label>
        <input
          type="text"
          name="email"
          id="email"
          onChange={this.handleChange}
          autoComplete="email"
        />
      </div>
      <div>
        <label>Password: </label>
        <input
          type="password"
          name="password"
          id="password"
          onChange={this.handleChange}
          autoComplete="new-password"
        />
      </div>
      <br />
      <div>

        <!-- HERE IS THE LINK I WANT TO DISABLE IN CASE OF INVALID FORM -->

        <Link when={this.state.formIsValid} to="/F2">
          <button
            onClick={() => {
              if (this.formIsValid()) {
                this.props.updatePurchaseRecord({
                  name: this.state.name,
                  email: this.state.email,
                  password: this.state.password,
                  purchase_id: this.props.purchase_id
                });
              }
            }}
          >
            Next
          </button>
        </Link>
      </div>
    </form> 

My formIsValid function that runs once the 'next' button is clicked:

  formIsValid() {
    let isValid = true;
    let formErrors = { name: "", email: "", password: "" };
    // validate name
    if (this.state.name === "") {
      isValid = false;
      formErrors.name = "Name is required";
    }

    // validate email
    if (this.state.email === "") {
      isValid = false;
      formErrors.email = "Email is required";
    }

    // validate password
    if (this.state.password === "") {
      isValid = false;
      formErrors.password = "Password is required";
    }
    this.setState({ formErrors });
    return isValid;
  }
mrwnt10
  • 1,234
  • 1
  • 17
  • 28

1 Answers1

1

Why not just render a disabled version of the button if the form is invalid? For example:

formIsValid ? <RealButton /> : <DisabledButton />
jsw324
  • 812
  • 7
  • 14
  • Would this allow me to perform the validation after the button has been clicked? I don't want to display my error messages until the user tries to click the button, so that they do not seem premature. – mrwnt10 Dec 19 '18 at 23:18
  • I suppose I could validate on the onMouseOver event for the button. – mrwnt10 Dec 19 '18 at 23:21
  • 1
    you can create a second click handler that handles the click of the disabled button. Alternatively, you can validate `onBlur` when the user clicks away from the input field. – jsw324 Dec 20 '18 at 01:00
  • What if there are like 12 ways a user could navigate away from a page and I want to prevent leaving the page in one place? I actually want to show my own modal and not the browser one preferably.. and include refreshing the page, back button, etc. – Kyle Zimmer Jun 01 '21 at 22:04