如何使用 Formik 进行输入清理?
How to use Input Sanitization with Formik?
我正在使用 useFormik
钩子将 Formik 用于我的表单。在配置中,我设置了 validate
、onSubmit
和 initialValues
键。我想清理我的输入,比如修剪和转义。对于电子邮件,我还想使用 validator.js
中的 normalizeEmail
。我找不到放置清理代码的位置 - 我是将它放在 formik 配置中还是在验证函数中。我意识到我可以使用 formik 中的 setFieldValue
,但我不想更改 formik.handleChange
功能,因为它处理表单状态并且不想搞砸它。
代码如下:
import { useEffect, useRef } from "react";
import { useSelector, useDispatch } from "react-redux";
import { NavLink as RouterLink, useHistory, useLocation } from "react-router-dom";
import Helmet from "react-helmet";
import {
Button,
LinearProgress,
Typography,
Paper,
Grid,
Box,
TextField
} from "@material-ui/core";
import useMediaQuery from "@material-ui/core/useMediaQuery";
import { useFormik } from "formik";
import { useSnackbar } from "notistack";
import CenterLayout from "../CenterLayout";
import { logInUser } from "../../features/user/userSlice";
import { useTheme } from "@material-ui/core/styles";
import { useTranslation } from "react-i18next";
import isEmail from 'validator/es/lib/isEmail';
const Login = () => {
const { isLoadingLogin, errorLoginCode } = useSelector((state) => state.user);
const prevIsLoadingLoginRef = useRef();
const dispatch = useDispatch();
const history = useHistory();
const location = useLocation();
const theme = useTheme();
const isXS = useMediaQuery(theme.breakpoints.down("xs"));
const { enqueueSnackbar } = useSnackbar();
const { t } = useTranslation();
const formik = useFormik({
initialValues: {
email: "",
password: "",
},
onSubmit: (values) => {
dispatch(logInUser(values));
},
validate: (values) => {
const errors = {};
if (!values.email) {
errors.email = t('form.required');
} else if (
!isEmail(values.email)
) {
errors.email = t('loginPage.invalidEmail');
}
if (!values.password) {
errors.password = t('form.required');
}
return errors;
},
});
useEffect(() => {
if (prevIsLoadingLoginRef.current && !isLoadingLogin) {
if (errorLoginCode.length === 0) {
formik.resetForm();
enqueueSnackbar(t("loginPage.loginSuccess"), {
variant: "success",
});
const { from } = location.state || { from: { pathname: "/dashboard" } };
history.replace(from);
} else {
enqueueSnackbar(
`${t("loginPage.loginFailed")}: ${t("api." + errorLoginCode)}`,
{ variant: "error" }
);
}
}
prevIsLoadingLoginRef.current = isLoadingLogin;
}, [
isLoadingLogin,
errorLoginCode,
history,
location,
formik,
enqueueSnackbar,
t,
]);
console.log("dbg1", formik);
return (
<CenterLayout>
<Helmet title="Circuittutor - Login" />
<Grid item xs={12} sm={8} md={4}>
<Paper elevation={isXS ? 0 : 1}>
<Box p={2}>
<Typography
variant="h6"
align="center"
color="secondary"
gutterBottom
>
{t("loginPage.form")}
</Typography>
<form onSubmit={formik.handleSubmit}>
<TextField
name="email"
type="email"
label={t("loginPage.email")}
fullWidth
style={{ marginBottom: theme.spacing(2) }}
value={formik.values.email}
onChange={formik.handleChange}
onBlur={formik.handleBlur}
error={
formik.touched.email &&
Boolean(formik.errors.email)
}
helperText={
formik.touched.email && formik.errors.email
}
/>
<TextField
name="password"
type="password"
label={t("loginPage.password")}
fullWidth
style={{ marginBottom: theme.spacing(2) }}
value={formik.values.password}
onChange={formik.handleChange}
onBlur={formik.handleBlur}
error={
formik.touched.password &&
Boolean(formik.errors.password)
}
helperText={
formik.touched.password && formik.errors.password
}
/>
{isLoadingLogin && (
<LinearProgress style={{ marginBottom: theme.spacing(2) }} />
)}
<Button
variant="contained"
color="secondary"
disabled={isLoadingLogin}
type="submit"
fullWidth={isXS}
>
{t("form.submit")}
</Button>
</form>
<Button
exact
variant="text"
disableElevation
color="primary"
component={RouterLink}
to="/forgotPassword"
style={{ marginTop: theme.spacing(2), padding: 0 }}
>
{t('loginPage.forgotPasswordBtn')}
</Button>
</Box>
</Paper>
</Grid>
</CenterLayout>
);
};
export default Login;
您需要做的就是拦截输入字段上的 onChange 事件,执行清理逻辑,然后使用新的计算值调用 setFieldValue
帮助程序。您无需担心与 Formik 内部结构相关的任何事情 - 这是提供自定义输入处理程序的官方方式
我正在使用 useFormik
钩子将 Formik 用于我的表单。在配置中,我设置了 validate
、onSubmit
和 initialValues
键。我想清理我的输入,比如修剪和转义。对于电子邮件,我还想使用 validator.js
中的 normalizeEmail
。我找不到放置清理代码的位置 - 我是将它放在 formik 配置中还是在验证函数中。我意识到我可以使用 formik 中的 setFieldValue
,但我不想更改 formik.handleChange
功能,因为它处理表单状态并且不想搞砸它。
代码如下:
import { useEffect, useRef } from "react";
import { useSelector, useDispatch } from "react-redux";
import { NavLink as RouterLink, useHistory, useLocation } from "react-router-dom";
import Helmet from "react-helmet";
import {
Button,
LinearProgress,
Typography,
Paper,
Grid,
Box,
TextField
} from "@material-ui/core";
import useMediaQuery from "@material-ui/core/useMediaQuery";
import { useFormik } from "formik";
import { useSnackbar } from "notistack";
import CenterLayout from "../CenterLayout";
import { logInUser } from "../../features/user/userSlice";
import { useTheme } from "@material-ui/core/styles";
import { useTranslation } from "react-i18next";
import isEmail from 'validator/es/lib/isEmail';
const Login = () => {
const { isLoadingLogin, errorLoginCode } = useSelector((state) => state.user);
const prevIsLoadingLoginRef = useRef();
const dispatch = useDispatch();
const history = useHistory();
const location = useLocation();
const theme = useTheme();
const isXS = useMediaQuery(theme.breakpoints.down("xs"));
const { enqueueSnackbar } = useSnackbar();
const { t } = useTranslation();
const formik = useFormik({
initialValues: {
email: "",
password: "",
},
onSubmit: (values) => {
dispatch(logInUser(values));
},
validate: (values) => {
const errors = {};
if (!values.email) {
errors.email = t('form.required');
} else if (
!isEmail(values.email)
) {
errors.email = t('loginPage.invalidEmail');
}
if (!values.password) {
errors.password = t('form.required');
}
return errors;
},
});
useEffect(() => {
if (prevIsLoadingLoginRef.current && !isLoadingLogin) {
if (errorLoginCode.length === 0) {
formik.resetForm();
enqueueSnackbar(t("loginPage.loginSuccess"), {
variant: "success",
});
const { from } = location.state || { from: { pathname: "/dashboard" } };
history.replace(from);
} else {
enqueueSnackbar(
`${t("loginPage.loginFailed")}: ${t("api." + errorLoginCode)}`,
{ variant: "error" }
);
}
}
prevIsLoadingLoginRef.current = isLoadingLogin;
}, [
isLoadingLogin,
errorLoginCode,
history,
location,
formik,
enqueueSnackbar,
t,
]);
console.log("dbg1", formik);
return (
<CenterLayout>
<Helmet title="Circuittutor - Login" />
<Grid item xs={12} sm={8} md={4}>
<Paper elevation={isXS ? 0 : 1}>
<Box p={2}>
<Typography
variant="h6"
align="center"
color="secondary"
gutterBottom
>
{t("loginPage.form")}
</Typography>
<form onSubmit={formik.handleSubmit}>
<TextField
name="email"
type="email"
label={t("loginPage.email")}
fullWidth
style={{ marginBottom: theme.spacing(2) }}
value={formik.values.email}
onChange={formik.handleChange}
onBlur={formik.handleBlur}
error={
formik.touched.email &&
Boolean(formik.errors.email)
}
helperText={
formik.touched.email && formik.errors.email
}
/>
<TextField
name="password"
type="password"
label={t("loginPage.password")}
fullWidth
style={{ marginBottom: theme.spacing(2) }}
value={formik.values.password}
onChange={formik.handleChange}
onBlur={formik.handleBlur}
error={
formik.touched.password &&
Boolean(formik.errors.password)
}
helperText={
formik.touched.password && formik.errors.password
}
/>
{isLoadingLogin && (
<LinearProgress style={{ marginBottom: theme.spacing(2) }} />
)}
<Button
variant="contained"
color="secondary"
disabled={isLoadingLogin}
type="submit"
fullWidth={isXS}
>
{t("form.submit")}
</Button>
</form>
<Button
exact
variant="text"
disableElevation
color="primary"
component={RouterLink}
to="/forgotPassword"
style={{ marginTop: theme.spacing(2), padding: 0 }}
>
{t('loginPage.forgotPasswordBtn')}
</Button>
</Box>
</Paper>
</Grid>
</CenterLayout>
);
};
export default Login;
您需要做的就是拦截输入字段上的 onChange 事件,执行清理逻辑,然后使用新的计算值调用 setFieldValue
帮助程序。您无需担心与 Formik 内部结构相关的任何事情 - 这是提供自定义输入处理程序的官方方式