Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

I can't use setInputValidationErrors and updateInputsWithError #89

Open
ipradella opened this issue May 2, 2018 · 3 comments
Open

I can't use setInputValidationErrors and updateInputsWithError #89

ipradella opened this issue May 2, 2018 · 3 comments
Labels

Comments

@ipradella
Copy link

ipradella commented May 2, 2018

I guys,

In order to asynchronously set an error on an input I'm trying to use the method updateInputsWithError so the behavior seems to me hazardous.

I tried to resolve my issue using a simple piece of code without async but it still no working.

I use the onChange callback of an input to check the value and I call updateInputsWithError to set an error message but nothing happens.

I also tried to force the isValid property used to display the error message but it didn't work.
When I print some logs on console i see that my input is rendered three times after the initial call of updateInputsWithError and the value of my errorMessage and the isValid property are overwritten.

find(collection, fn) {
    for (let i = 0, l = collection.length; i < l; i += 1) {
      const item = collection[i];
      if (fn(item)) {
        return item;
      }
    }
    return null;
  }

  onChange = () => {
    const component = this.find(this.form.inputs, input => input.props.name === 'email');
    this.form.updateInputsWithError({email : 'error tutulapin'});
    component.setState({
      isValid: false,
    });
  };

  render() {
    return (
      <Formsy onValidSubmit={this.submit} onValid={this.enableButton} onInvalid={this.disableButton} ref={instance => (this.form = instance)}>
        <MyInput
          name="email"
          onChange={this.onChange}
        />
        <button type="submit" disabled={!this.state.canSubmit}>Submit</button>
      </Formsy>
    );
  }

My Input

render() {
    // An error message is returned only if the component is invalid
    const errorMessage = this.props.getErrorMessage();
    console.log(this.props.isValid(), this.props.showRequired(), errorMessage);

    return (
      <div>
        <input
          onChange={this.changeValue}
          type="text"
          value={this.props.getValue() || ''}
        />
        <span>{errorMessage}</span>
      </div>
    );
  }

image

Thanks in advance for your help.

@MilosRasic
Copy link
Contributor

Hi, @ipradella, sorry for the late response. I tried your code and it works for me, but I don't have your changeValue() method. I believe your problem may lie there. Here's how I did it:

  changeValue(event) {
    // setValue() will set the value of the component, which in
    // turn will validate it and the rest of the form
    // Important: Don't skip this step. This pattern is required
    // for Formsy to work.
    this.props.setValue(event.currentTarget.value, false);

    if (this.props.onChange) {
      this.props.onChange();
    }
  }

@MilosRasic
Copy link
Contributor

Ok, after a more in-depth look, you shouldn't have to adapt the implementation of your component to how you want to use it (referring to the false argument in setValue() call).

This is definitely a difficult problem. I think normally updateInputsWithErrors() is intended to be used in onValidSubmit handler, so that you can set server-side errors even though the form passed client-side validation. I can definitely see the need to server-side validate a single field, for example to check if a username is taken.

The problem is that setValue() calls setState(), then in the callback calls validate() which in turn calls setState() again. It's a mess. In your case, the first setState() call sets the new value, but then the onChange() call happens before the setState() callback, so the updateInputsWithErrors() is called first, then validation takes place and overwrites the validity status.

There's no easy way out. Any fix is going to have to be in 2.0. I want to do a state refactoring that would hopefully reduce the number of setState() and unnecessary rerenders, so hopefully this scenario will become more predictable.

@rkuykendall
Copy link
Member

@ipradella Would this be solved by #112 ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants