簡體   English   中英

react-hook-form:使用 onBlur 模式時驗證不起作用

[英]react-hook-form: Validation not working when using onBlur mode

當用戶選擇超過 5 個復選框但沒有成功時,我試圖用yupreact-hook-form顯示錯誤。

相反,錯誤會在選中第七個復選框時顯示。

這是簡化的代碼:

imports...

const schema = yup.object().shape({
  option: yup.array().max(5)
});
function App() {
  const { register, handleSubmit, errors } = useForm({
    mode: "onBlur",
    resolver: yupResolver(schema)
  });

  const [state, setState] = useState({
    wasSubmitted: false
  });

  const submit = async (data) => {
    window.alert(JSON.stringify(data));
  };

  if (state.wasSubmitted) {
    return <p>Congrats</p>;
  } else {
    return (
      <>
        <CssBaseline />
        <Container maxWidth="sm">
          <Typography variant="h2" component="h1">
            My form
          </Typography>
          <form noValidate autoComplete="off" onSubmit={handleSubmit(submit)}>
            <FormControl
              component="fieldset"
              error={!!errors.option}
            >
              <FormLabel component="legend">
                Please select the category or categories of books the child is
                interested in:
              </FormLabel>
              <FormGroup>
                <FormControlLabel
                  control={<Checkbox name="option" inputRef={register} />}
                  value="Option1"
                  label="Option 1"
                />
                <FormControlLabel
                  control={<Checkbox name="option" inputRef={register} />}
                  value="Option2"
                  label="Option 2"
                />
                <FormControlLabel
                  control={<Checkbox name="option" inputRef={register} />}
                  label="Option3"
                  value="Option 3"
                />
                <FormControlLabel
                  control={<Checkbox name="option" inputRef={register} />}
                  value="Option4"
                  label="Option 4"
                />
                <FormControlLabel
                  control={<Checkbox name="option" inputRef={register} />}
                  value="Option5"
                  label="Option 5"
                />
                <FormControlLabel
                  control={<Checkbox name="option" inputRef={register} />}
                  value="Option6"
                  label="Option 6"
                />
                <FormControlLabel
                  control={<Checkbox name="option" inputRef={register} />}
                  value="Option7"
                  label="Option 7"
                />
                <FormControlLabel
                  control={<Checkbox name="option" inputRef={register} />}
                  value="Option8"
                  label="Option 8"
                />
                <FormControlLabel
              <FormHelperText>Up to five categories</FormHelperText>
            </FormControl>

            <Button
              type="submit"
              disableElevation
            >
              Submit
            </Button>
          </form>
        </Container>
      </>
    );
  }
}

export default App;

您還可以在此處找到該項目的沙箱:

編輯 modern-resonance-d7mpc

有任何想法嗎?

正如@aadlc 所說,解決方案是將模式設置為onChangeall 我會解釋原因。

來自 react-hook-form API 文檔

mode: onChange | onBlur | onSubmit | onTouched | all = 'onSubmit'

姓名 類型 描述
onSubmit(默認) 細繩 驗證將在submit事件上觸發,無效輸入將附加onChange事件偵聽器以重新驗證它們。
模糊 細繩 驗證將在blur事件上觸發。
改變 細繩 驗證將在每個輸入的change事件上觸發,並導致多次重新渲染。 警告:這通常會對性能產生重大影響。
onTouched 細繩 驗證將在第一個blur事件上觸發。 之后,它將在每個change事件上觸發。
全部 細繩 驗證將在blurchange事件上觸發。

在您的代碼中,表單模式為onBlur 這意味着驗證是在blur事件上觸發的(不聚焦輸入)。 當您 select 選項n+1時,它會從選項n觸發模糊事件。

例如,就在您 select 第 6 個選項(無效)之前, blur事件從第 5 個選項(有效)觸發,因為您不再關注它,並從選項 1-5 進行驗證,因此您必須檢查第 7 個選項以重新驗證從 1 到 6 的選項。

-- select up to 5 options --
select option 4

blur event fires from option 4 -> validate -> pass
select option 5

blur event fires from option 5 -> validate -> pass
select option 6

blur event fires from option 6 -> validate -> fail
select option 7

將驗證模式更改為onChange將在觸發change事件驗證,此時所有值都是最新的:

-- select up to 5 options --
select option 4

blur event fires from option 4
select option 5
change event fires from option 5 -> validate -> pass

blur event fires from option 5
select option 6
change event fires from option 6 -> validate -> fail

blur event fires from option 6
select option 7
change event fires from option 7 -> validate -> fail

將 valiation 模式更改為all將在blurchange事件中進行驗證,這在此工作流程中可能是多余的,但它也有效。

如果您使用的是受控組件,onBlur 可能不會自動觸發。 您將必須手動連接它:

使用控制器文檔
包裝文檔

export const MyControlledField = ({ fieldName }: { fieldName: string }) => {
  const methods = useFormContext();
  const value = useWatch({ name: fieldName });
  const controller = useController({
    name: fieldName,
    control: methods.control,
  });
  return (
    <TextField
      value={value ?? ''}
      onChange={(e) => {
        methods.setValue(fieldName, e.target.value);
      }}
      onBlur={controller.field.onBlur}
    />
  );
};

或者使用包裝組件:

export const MyWrappedField = ({ fieldName }: { fieldName: string }) => {
  const methods = useFormContext();

  return (
    <Controller
      control={methods.control}
      name={fieldName}
      render={({ field: { onChange, onBlur, value, name, ref }, fieldState, formState }) => (
        <TextField
          onBlur={onBlur}
          onChange={onChange}
          value={value}
          inputRef={ref}
        />
      )}
    />
  );
};

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM