formula-one icon indicating copy to clipboard operation
formula-one copied to clipboard

Synchronously calling onChange after onBlur does not set blurred metadata

Open uforic opened this issue 6 years ago • 1 comments

Description

Feel free to chalk this up to user error, but ran into the following today:

<Field link={links.phone_number} validation={validateUSPhoneNumber}>
  {(value, errors, onChange, onBlur) => (
    <LabelErrorWrapper label="Your phone number" errors={errors}>
      <TextInput
        type="tel"
        value={value}
        onChange={event => {
          onChange(event.target.value);
        }}
        onBlur={() => {
          onBlur();
          onChange(formatPhoneNumberInput(value));
        }}
        id={'phone_number'}
      />
    </LabelErrorWrapper>
  )}
</Field>

The above code will never show errors, even after you've blurred. The reason why is that the blur metadata for the field never gets set to true.

I think this is because both functions are basically set state, and I think you have something like:

// onBlur
this.setState({...otherStuff, blurred: true);
// onChange
this.setState({...otherStuff, blurred: prevState.blurred});

Because they are run async, the second one blows away the first.

If I switch the order, it then works, because under the hood I suspect this happens:

// onChange
this.setState({...otherStuff, blurred: prevState.blurred});
// onBlur
this.setState({...otherStuff, blurred: true);

I'm unblocked (by switching the order), but wonder if onChange should not set the blur state, and risk clobbering onBlur.

Alternately, if I'm doing something wrong, and should be "prettifying" phone numbers upon blur in some other way, let me know!

uforic avatar Sep 11 '19 17:09 uforic

Great bug report @uforic.

dmnd avatar Sep 16 '19 17:09 dmnd