React Hook Form - Typescript 问题和错误处理?
React Hook Form - Typescript issues and error handling?
我目前正在从 Formik 切换到 React Hook Form。我也在使用 Material UI V5 和 yup 进行验证。
我现在有两个问题要解决:
- 各种 RHF 道具和选项弹出 TS 错误。
- 我希望能够同时验证 onBlur 和 onSubmit,但 HTML5 验证当前显示 onSubmit。
这是我的代码:
import { useForm, Controller } from 'react-hook-form';
import { yupResolver } from '@hookform/resolvers/yup';
import {
Box,
Button,
CircularProgress,
Grid,
InputAdornment,
TextField,
Theme,
Typography,
useMediaQuery,
} from '@mui/material';
import { validationSchema } from './validationSchema'
const LoginForm: React.FC = () => {
const {
control,
handleSubmit,
formState: { errors },
} = useForm({
resolver: yupResolver(validationSchema),
mode: 'onBlur',
reValidateMode: 'onChange',
defaultValues: { // <-- TS Error: Type '{ email: string; password: string; }' is not assignable to type '{ [x: string]: undefined; email?: string | undefined; password?: string | undefined; }'.
email: '',
password: '',
},
});
const handleSignin = async (credentials: Values) => {
const { error } = await signIn(Provider.Email, credentials);
if (error) {
setLoadingLogin(false);
setLoginError(true);
} else {
router.push('/');
}
};
return (
<BoxContainer>
<form onSubmit={handleSubmit(handleSignin)}>
<Grid container spacing={2}>
<Grid item xs={12}>
<Controller
name="email" // <-- TS Error: Type 'string' is not assignable to type 'never'.
control={control}
render={({ field }) => (
<TextField
{...field}
error={!!errors?.email}
helperText={errors?.email?.message} // <-- TS Error: Property 'message' does not exist on type 'never'.
size="small"
autoFocus
label="Email"
fullWidth
autoComplete="email"
type="email"
variant="outlined"
InputProps={{
startAdornment: (
<InputAdornment position="start">
<EmailIcon />
</InputAdornment>
),
}}
/>
)}
/>
</Grid>
<Grid item xs={12}>
<Controller
name="password" // <-- TS Error: Type 'string' is not assignable to type 'never'.
error={!!errors?.password}
helperText={errors?.password?.message} // <-- TS Error: Property 'message' does not exist on type 'never'.
control={control}
render={({ field }) => (
<TextField
{...field}
size="small"
autoComplete="password"
label="Password"
fullWidth
type="password"
variant="outlined"
InputProps={{
startAdornment: (
<InputAdornment position="start">
<LockIcon />
</InputAdornment>
),
}}
/>
)}
/>
</Grid>
{loginError && (
<Grid item xs={12}>
<Alert severity="error">
There was an error logging in.
<br /> Please try again.
</Alert>
</Grid>
)}
<Grid item xs={12}>
<Button
color="primary"
// disabled={isSubmitting || loadingLogin}
disableElevation
disableRipple
fullWidth
size="large"
type="submit"
variant="contained">
Signin
</Button>
</Grid>
<Grid item xs={12}>
<Typography
variant="body2"
color="textSecondary"
className="text-center">
Don't have an account?{' '}
<Link href="/register">
<a>Signup</a>
</Link>
</Typography>
{!isDesktop && (
<Box marginTop={2}>
<Typography
variant="body1"
color="textSecondary"
className="text-center">
<Link href="/forgot-password">
<a>Forgot your password?</a>
</Link>
</Typography>
</Box>
)}
<Box mt={2} className="text-center">
<Typography
variant="subtitle2"
color="textSecondary"
className="mt-4">
By continuing to use GearCloset, you agree to our{' '}
<Link href="/terms-and-conditions">
<a>Terms and Conditions.</a>
</Link>
</Typography>
</Box>
</Grid>
</Grid>
</form>
</BoxContainer>
);
}
我在代码旁边评论了 return TS 错误。
第二个问题是,当我输入无效或空白的电子邮件然后按 Tab 键时,输入的错误状态正常工作,但是当我按下提交按钮时,电子邮件输入显示正常 HTML5 验证警告。我希望模式以某种方式既是 onBlur 又是 onSubmit。
此时,RHF 似乎可以,我只是在清理错误和功能。
我认为您的第一个问题可以链接到这个公开 Github issue. There is a workaround, check this SO .
对于第二个,您必须在 <form />
元素上设置 noValidate
属性并让 RHF 完全处理验证。
<form onSubmit={handleSubmit(handleSignin)} noValidate>
我目前正在从 Formik 切换到 React Hook Form。我也在使用 Material UI V5 和 yup 进行验证。
我现在有两个问题要解决:
- 各种 RHF 道具和选项弹出 TS 错误。
- 我希望能够同时验证 onBlur 和 onSubmit,但 HTML5 验证当前显示 onSubmit。
这是我的代码:
import { useForm, Controller } from 'react-hook-form';
import { yupResolver } from '@hookform/resolvers/yup';
import {
Box,
Button,
CircularProgress,
Grid,
InputAdornment,
TextField,
Theme,
Typography,
useMediaQuery,
} from '@mui/material';
import { validationSchema } from './validationSchema'
const LoginForm: React.FC = () => {
const {
control,
handleSubmit,
formState: { errors },
} = useForm({
resolver: yupResolver(validationSchema),
mode: 'onBlur',
reValidateMode: 'onChange',
defaultValues: { // <-- TS Error: Type '{ email: string; password: string; }' is not assignable to type '{ [x: string]: undefined; email?: string | undefined; password?: string | undefined; }'.
email: '',
password: '',
},
});
const handleSignin = async (credentials: Values) => {
const { error } = await signIn(Provider.Email, credentials);
if (error) {
setLoadingLogin(false);
setLoginError(true);
} else {
router.push('/');
}
};
return (
<BoxContainer>
<form onSubmit={handleSubmit(handleSignin)}>
<Grid container spacing={2}>
<Grid item xs={12}>
<Controller
name="email" // <-- TS Error: Type 'string' is not assignable to type 'never'.
control={control}
render={({ field }) => (
<TextField
{...field}
error={!!errors?.email}
helperText={errors?.email?.message} // <-- TS Error: Property 'message' does not exist on type 'never'.
size="small"
autoFocus
label="Email"
fullWidth
autoComplete="email"
type="email"
variant="outlined"
InputProps={{
startAdornment: (
<InputAdornment position="start">
<EmailIcon />
</InputAdornment>
),
}}
/>
)}
/>
</Grid>
<Grid item xs={12}>
<Controller
name="password" // <-- TS Error: Type 'string' is not assignable to type 'never'.
error={!!errors?.password}
helperText={errors?.password?.message} // <-- TS Error: Property 'message' does not exist on type 'never'.
control={control}
render={({ field }) => (
<TextField
{...field}
size="small"
autoComplete="password"
label="Password"
fullWidth
type="password"
variant="outlined"
InputProps={{
startAdornment: (
<InputAdornment position="start">
<LockIcon />
</InputAdornment>
),
}}
/>
)}
/>
</Grid>
{loginError && (
<Grid item xs={12}>
<Alert severity="error">
There was an error logging in.
<br /> Please try again.
</Alert>
</Grid>
)}
<Grid item xs={12}>
<Button
color="primary"
// disabled={isSubmitting || loadingLogin}
disableElevation
disableRipple
fullWidth
size="large"
type="submit"
variant="contained">
Signin
</Button>
</Grid>
<Grid item xs={12}>
<Typography
variant="body2"
color="textSecondary"
className="text-center">
Don't have an account?{' '}
<Link href="/register">
<a>Signup</a>
</Link>
</Typography>
{!isDesktop && (
<Box marginTop={2}>
<Typography
variant="body1"
color="textSecondary"
className="text-center">
<Link href="/forgot-password">
<a>Forgot your password?</a>
</Link>
</Typography>
</Box>
)}
<Box mt={2} className="text-center">
<Typography
variant="subtitle2"
color="textSecondary"
className="mt-4">
By continuing to use GearCloset, you agree to our{' '}
<Link href="/terms-and-conditions">
<a>Terms and Conditions.</a>
</Link>
</Typography>
</Box>
</Grid>
</Grid>
</form>
</BoxContainer>
);
}
我在代码旁边评论了 return TS 错误。
第二个问题是,当我输入无效或空白的电子邮件然后按 Tab 键时,输入的错误状态正常工作,但是当我按下提交按钮时,电子邮件输入显示正常 HTML5 验证警告。我希望模式以某种方式既是 onBlur 又是 onSubmit。
此时,RHF 似乎可以,我只是在清理错误和功能。
我认为您的第一个问题可以链接到这个公开 Github issue. There is a workaround, check this SO
对于第二个,您必须在 <form />
元素上设置 noValidate
属性并让 RHF 完全处理验证。
<form onSubmit={handleSubmit(handleSignin)} noValidate>