Search code examples
reactjsmaterial-uiformikformik-material-ui

MUI & Formik: Validation doesn't trigger for useField


Codesandbox with minimal working example: https://codesandbox.io/s/mystifying-lake-m0oxc?file=/src/DemoForm.tsx

Essentially, I have a AutoComplete dropdown which is tied into a Formik form with the useField hook. This sets the value correctly on any change, but the validation doesn't seem to trigger when I expect it to.

Validation runs successfully and removes the error if:

  1. Another field is changed
  2. I click on the "background" after selecting a value in the dropdown

What I expected and wanted was that the validation should run immediately when a value is selected.

To reproduce:

  1. Click the category dropdown
  2. Select a value, which closes the dropdown
  3. Confirm that the error is still indicated (on the field and in the printout)
  4. Click elsewhere on the screen. This should trigger validation and clear the error.

Any suggestions?

Edit: I've tested an equivalent implementation with react-select as the dropdown and had the same issue, so I don't think it's directly tied to MUI.


Solution

  • I just reproduced based on the working example what you provided and realized that you set helpers.setTouched manually.

    Just don't overuse the setTouched and also you need to handle if you remove the selected item from the autocomplete.

          <Autocomplete
            disablePortal
            id="category-selector"
            options={options}
            onBlur={() => helpers.setTouched(true, true)}
            isOptionEqualToValue={(option, value) => option.id === value.id}
            onOpen={() => helpers.setTouched(true, true)}
            onChange={(_, option) => {
              if (option) {
                helpers.setValue(option.id);
              } else {
                helpers.setValue(0);
              }
            }}
            renderInput={(params) => (
              <TextField
                {...params}
                label="Category"
                error={meta.touched && Boolean(meta.error)}
              />
            )}
          />