replace formik with react-hook-form
This commit is contained in:
parent
f6abf2bc38
commit
c14a2bc082
@ -14,15 +14,16 @@
|
||||
"@emotion/react": "^11.10.6",
|
||||
"@emotion/styled": "^11.10.6",
|
||||
"@fontsource/roboto": "^4.5.8",
|
||||
"@hookform/resolvers": "^2.9.11",
|
||||
"@mui/icons-material": "^5.11.9",
|
||||
"@mui/material": "^5.11.9",
|
||||
"@next/font": "13.1.6",
|
||||
"axios": "^1.3.3",
|
||||
"formik": "^2.2.9",
|
||||
"http-status": "^1.6.2",
|
||||
"next": "13.1.6",
|
||||
"react": "18.2.0",
|
||||
"react-dom": "18.2.0",
|
||||
"react-hook-form": "^7.43.2",
|
||||
"react-toastify": "^9.1.1",
|
||||
"swr": "^2.0.3",
|
||||
"yup": "^1.0.0"
|
||||
|
@ -4,6 +4,7 @@ specifiers:
|
||||
'@emotion/react': ^11.10.6
|
||||
'@emotion/styled': ^11.10.6
|
||||
'@fontsource/roboto': ^4.5.8
|
||||
'@hookform/resolvers': ^2.9.11
|
||||
'@mui/icons-material': ^5.11.9
|
||||
'@mui/material': ^5.11.9
|
||||
'@next/font': 13.1.6
|
||||
@ -14,7 +15,6 @@ specifiers:
|
||||
eslint: ^8.34.0
|
||||
eslint-config-next: ^13.1.6
|
||||
eslint-config-prettier: ^8.6.0
|
||||
formik: ^2.2.9
|
||||
http-status: ^1.6.2
|
||||
husky: ^8.0.0
|
||||
lint-staged: ^13.1.2
|
||||
@ -22,6 +22,7 @@ specifiers:
|
||||
prettier: 2.8.4
|
||||
react: 18.2.0
|
||||
react-dom: 18.2.0
|
||||
react-hook-form: ^7.43.2
|
||||
react-toastify: ^9.1.1
|
||||
swr: ^2.0.3
|
||||
typescript: ^4.9.5
|
||||
@ -31,15 +32,16 @@ dependencies:
|
||||
'@emotion/react': 11.10.6_pmekkgnqduwlme35zpnqhenc34
|
||||
'@emotion/styled': 11.10.6_oouaibmszuch5k64ms7uxp2aia
|
||||
'@fontsource/roboto': 4.5.8
|
||||
'@hookform/resolvers': 2.9.11_react-hook-form@7.43.2
|
||||
'@mui/icons-material': 5.11.9_ofpk46txu7v2f5mzrtv4xsczka
|
||||
'@mui/material': 5.11.9_xqeqsl5kvjjtyxwyi3jhw3yuli
|
||||
'@next/font': 13.1.6
|
||||
axios: 1.3.3
|
||||
formik: 2.2.9_react@18.2.0
|
||||
http-status: 1.6.2
|
||||
next: 13.1.6_biqbaboplfbrettd7655fr4n2y
|
||||
react: 18.2.0
|
||||
react-dom: 18.2.0_react@18.2.0
|
||||
react-hook-form: 7.43.2_react@18.2.0
|
||||
react-toastify: 9.1.1_biqbaboplfbrettd7655fr4n2y
|
||||
swr: 2.0.3_react@18.2.0
|
||||
yup: 1.0.0
|
||||
@ -243,6 +245,14 @@ packages:
|
||||
resolution: {integrity: sha512-CnD7zLItIzt86q4Sj3kZUiLcBk1dSk81qcqgMGaZe7SQ1P8hFNxhMl5AZthK1zrDM5m74VVhaOpuMGIL4gagaA==}
|
||||
dev: false
|
||||
|
||||
/@hookform/resolvers/2.9.11_react-hook-form@7.43.2:
|
||||
resolution: {integrity: sha512-bA3aZ79UgcHj7tFV7RlgThzwSSHZgvfbt2wprldRkYBcMopdMvHyO17Wwp/twcJasNFischFfS7oz8Katz8DdQ==}
|
||||
peerDependencies:
|
||||
react-hook-form: ^7.0.0
|
||||
dependencies:
|
||||
react-hook-form: 7.43.2_react@18.2.0
|
||||
dev: false
|
||||
|
||||
/@humanwhocodes/config-array/0.11.8:
|
||||
resolution: {integrity: sha512-UybHIJzJnR5Qc/MsD9Kr+RpO2h+/P1GhOwdiLPXK5TWk5sgTdu88bTD9UP+CKbPPh5Rni1u0GjAdYQLemG8g+g==}
|
||||
engines: {node: '>=10.10.0'}
|
||||
@ -1104,11 +1114,6 @@ packages:
|
||||
resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==}
|
||||
dev: true
|
||||
|
||||
/deepmerge/2.2.1:
|
||||
resolution: {integrity: sha512-R9hc1Xa/NOBi9WRVUWg19rl1UB7Tt4kuPd+thNJgFZoxXsTz7ncaPaeIm+40oSGuP33DfMb4sZt1QIGiJzC4EA==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
dev: false
|
||||
|
||||
/define-lazy-prop/2.0.0:
|
||||
resolution: {integrity: sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==}
|
||||
engines: {node: '>=8'}
|
||||
@ -1668,21 +1673,6 @@ packages:
|
||||
mime-types: 2.1.35
|
||||
dev: false
|
||||
|
||||
/formik/2.2.9_react@18.2.0:
|
||||
resolution: {integrity: sha512-LQLcISMmf1r5at4/gyJigGn0gOwFbeEAlji+N9InZF6LIMXnFNkO42sCI8Jt84YZggpD4cPWObAZaxpEFtSzNA==}
|
||||
peerDependencies:
|
||||
react: '>=16.8.0'
|
||||
dependencies:
|
||||
deepmerge: 2.2.1
|
||||
hoist-non-react-statics: 3.3.2
|
||||
lodash: 4.17.21
|
||||
lodash-es: 4.17.21
|
||||
react: 18.2.0
|
||||
react-fast-compare: 2.0.4
|
||||
tiny-warning: 1.0.3
|
||||
tslib: 1.14.1
|
||||
dev: false
|
||||
|
||||
/fs.realpath/1.0.0:
|
||||
resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==}
|
||||
dev: true
|
||||
@ -2233,18 +2223,10 @@ packages:
|
||||
p-locate: 5.0.0
|
||||
dev: true
|
||||
|
||||
/lodash-es/4.17.21:
|
||||
resolution: {integrity: sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==}
|
||||
dev: false
|
||||
|
||||
/lodash.merge/4.6.2:
|
||||
resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==}
|
||||
dev: true
|
||||
|
||||
/lodash/4.17.21:
|
||||
resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==}
|
||||
dev: false
|
||||
|
||||
/log-update/4.0.0:
|
||||
resolution: {integrity: sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg==}
|
||||
engines: {node: '>=10'}
|
||||
@ -2629,8 +2611,13 @@ packages:
|
||||
scheduler: 0.23.0
|
||||
dev: false
|
||||
|
||||
/react-fast-compare/2.0.4:
|
||||
resolution: {integrity: sha512-suNP+J1VU1MWFKcyt7RtjiSWUjvidmQSlqu+eHslq+342xCbGTYmC0mEhPCOHxlW0CywylOC1u2DFAT+bv4dBw==}
|
||||
/react-hook-form/7.43.2_react@18.2.0:
|
||||
resolution: {integrity: sha512-NvD3Oe2Y9hhqo2R4I4iJigDzSLpdMnzUpNMxlnzTbdiT7NT3BW0GxWCzEtwPudZMUPbZhNcSy1EcGAygyhDORg==}
|
||||
engines: {node: '>=12.22.0'}
|
||||
peerDependencies:
|
||||
react: ^16.8.0 || ^17 || ^18
|
||||
dependencies:
|
||||
react: 18.2.0
|
||||
dev: false
|
||||
|
||||
/react-is/16.13.1:
|
||||
@ -3012,10 +2999,6 @@ packages:
|
||||
globrex: 0.1.2
|
||||
dev: true
|
||||
|
||||
/tiny-warning/1.0.3:
|
||||
resolution: {integrity: sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==}
|
||||
dev: false
|
||||
|
||||
/to-fast-properties/2.0.0:
|
||||
resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==}
|
||||
engines: {node: '>=4'}
|
||||
@ -3043,6 +3026,7 @@ packages:
|
||||
|
||||
/tslib/1.14.1:
|
||||
resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==}
|
||||
dev: true
|
||||
|
||||
/tslib/2.5.0:
|
||||
resolution: {integrity: sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==}
|
||||
|
@ -1,6 +1,5 @@
|
||||
import * as React from 'react'
|
||||
import { useUser } from '@/utils/useUser'
|
||||
import { useFormik } from 'formik'
|
||||
import { useRouter } from 'next/router'
|
||||
import Button from '@mui/material/Button'
|
||||
import TextField from '@mui/material/TextField'
|
||||
@ -16,6 +15,8 @@ import * as yup from '@/utils/validation'
|
||||
import * as api from '@/api'
|
||||
import { useCountdown, COUNTDOWN_SECONDS } from '@/utils/useCountdown'
|
||||
import { toast } from 'react-toastify'
|
||||
import { useForm, SubmitHandler } from 'react-hook-form'
|
||||
import { yupResolver } from '@hookform/resolvers/yup'
|
||||
|
||||
export function DeleteUser() {
|
||||
const { user } = useUser()
|
||||
@ -24,33 +25,33 @@ export function DeleteUser() {
|
||||
const [confirm, setConfrim] = React.useState(false)
|
||||
const { countdown, setCountdown } = useCountdown()
|
||||
|
||||
const formik = useFormik<DeleteUser>({
|
||||
initialValues: {
|
||||
const hookForm = useForm<DeleteUser>({
|
||||
mode: 'onTouched',
|
||||
defaultValues: {
|
||||
email: user!.email,
|
||||
password: '',
|
||||
verifyCode: '',
|
||||
token: '',
|
||||
},
|
||||
validationSchema: yup.object({
|
||||
verifyCode: yup.verifyCodeSchema,
|
||||
password: yup.string().required('请输入密码'),
|
||||
}),
|
||||
onSubmit: async (values) => {
|
||||
await api.user.deleteUser(values)
|
||||
localStorage.removeItem('accessToken')
|
||||
toast.success('用户删除成功')
|
||||
router.push('/login')
|
||||
},
|
||||
resolver: yupResolver(
|
||||
yup.object({
|
||||
verifyCode: yup.verifyCodeSchema,
|
||||
password: yup.string().required('请输入密码'),
|
||||
}),
|
||||
),
|
||||
})
|
||||
const onSubmit: SubmitHandler<DeleteUser> = async (values) => {
|
||||
await api.user.deleteUser(values)
|
||||
localStorage.removeItem('accessToken')
|
||||
toast.success('用户删除成功')
|
||||
router.push('/login')
|
||||
}
|
||||
|
||||
async function sendVerifyCode() {
|
||||
setCountdown(COUNTDOWN_SECONDS)
|
||||
try {
|
||||
const res = await api.email.sendEmailVerifyCode({
|
||||
email: formik.values.email,
|
||||
email: hookForm.getValues('email'),
|
||||
scene: EmailVerifyCodeScene.deleteUser,
|
||||
})
|
||||
formik.setFieldValue('token', res.data.token)
|
||||
hookForm.setValue('token', res.data.token)
|
||||
} catch (err) {
|
||||
setCountdown(0)
|
||||
}
|
||||
@ -73,7 +74,7 @@ export function DeleteUser() {
|
||||
<Grid container spacing={[2, 1]}>
|
||||
<Grid xs={12}>
|
||||
<TextField
|
||||
{...formik.getFieldProps('email')}
|
||||
{...hookForm.register('email')}
|
||||
disabled
|
||||
helperText=" "
|
||||
fullWidth
|
||||
@ -82,15 +83,14 @@ export function DeleteUser() {
|
||||
</Grid>
|
||||
<Grid xs={8}>
|
||||
<TextField
|
||||
{...formik.getFieldProps('verifyCode')}
|
||||
{...hookForm.register('verifyCode')}
|
||||
required
|
||||
error={formik.touched.verifyCode && !!formik.errors.verifyCode}
|
||||
error={!!hookForm.formState.errors.verifyCode}
|
||||
helperText={
|
||||
(formik.touched.verifyCode && formik.errors.verifyCode) || ' '
|
||||
hookForm.formState.errors.verifyCode?.message || ' '
|
||||
}
|
||||
fullWidth
|
||||
label="验证码"
|
||||
autoComplete="verifyCode"
|
||||
/>
|
||||
</Grid>
|
||||
<Grid xs={4}>
|
||||
@ -107,12 +107,10 @@ export function DeleteUser() {
|
||||
</Grid>
|
||||
<Grid xs={12}>
|
||||
<TextField
|
||||
{...formik.getFieldProps('password')}
|
||||
{...hookForm.register('password')}
|
||||
required
|
||||
error={formik.touched.password && !!formik.errors.password}
|
||||
helperText={
|
||||
(formik.touched.password && formik.errors.password) || ' '
|
||||
}
|
||||
error={!!hookForm.formState.errors.password}
|
||||
helperText={hookForm.formState.errors.password?.message || ' '}
|
||||
fullWidth
|
||||
label="密码"
|
||||
type="password"
|
||||
@ -139,7 +137,7 @@ export function DeleteUser() {
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<Button onClick={() => setConfrim(false)}>取消</Button>
|
||||
<Button color="error" onClick={formik.submitForm}>
|
||||
<Button color="error" onClick={hookForm.handleSubmit(onSubmit)}>
|
||||
确定删除
|
||||
</Button>
|
||||
</DialogActions>
|
||||
|
@ -6,7 +6,6 @@ import Grid from '@mui/material/Unstable_Grid2'
|
||||
import KeyIcon from '@mui/icons-material/Key'
|
||||
import Typography from '@mui/material/Typography'
|
||||
import Container from '@mui/material/Container'
|
||||
import { useFormik } from 'formik'
|
||||
import { useRouter } from 'next/router'
|
||||
import * as yup from '@/utils/validation'
|
||||
import * as api from '@/api'
|
||||
@ -14,43 +13,42 @@ import { ForgetPasswordInputDto } from '@/api/user.interface'
|
||||
import { EmailVerifyCodeScene } from '@/api/email.interface'
|
||||
import { useCountdown, COUNTDOWN_SECONDS } from '@/utils/useCountdown'
|
||||
import { toast } from 'react-toastify'
|
||||
import { useForm, SubmitHandler } from 'react-hook-form'
|
||||
import { yupResolver } from '@hookform/resolvers/yup'
|
||||
|
||||
export default function ForgetPassword() {
|
||||
const router = useRouter()
|
||||
const { countdown, setCountdown } = useCountdown()
|
||||
|
||||
const formik = useFormik<ForgetPasswordInputDto>({
|
||||
initialValues: {
|
||||
email: '',
|
||||
password: '',
|
||||
verifyCode: '',
|
||||
token: '',
|
||||
userId: '',
|
||||
},
|
||||
validationSchema: yup.object({
|
||||
email: yup.emailSchema,
|
||||
password: yup.passwordSchema,
|
||||
verifyCode: yup.verifyCodeSchema,
|
||||
}),
|
||||
onSubmit: async (values) => {
|
||||
const res = await api.user.forgetPassword(values)
|
||||
localStorage.setItem('accessToken', res.data)
|
||||
toast.success('密码重置成功!', {
|
||||
onClose: () => router.push('/login'),
|
||||
})
|
||||
},
|
||||
const hookForm = useForm<ForgetPasswordInputDto>({
|
||||
mode: 'onTouched',
|
||||
resolver: yupResolver(
|
||||
yup.object({
|
||||
email: yup.emailSchema,
|
||||
password: yup.passwordSchema,
|
||||
verifyCode: yup.verifyCodeSchema,
|
||||
}),
|
||||
),
|
||||
})
|
||||
const onSubmit: SubmitHandler<ForgetPasswordInputDto> = async (values) => {
|
||||
const res = await api.user.forgetPassword(values)
|
||||
localStorage.setItem('accessToken', res.data)
|
||||
toast.success('密码重置成功!', {
|
||||
onClose: () => router.push('/login'),
|
||||
})
|
||||
}
|
||||
|
||||
async function sendVerifyCode() {
|
||||
await formik.validateField('email')
|
||||
const isValid = await hookForm.trigger('email')
|
||||
if (!isValid) return
|
||||
setCountdown(COUNTDOWN_SECONDS)
|
||||
try {
|
||||
const res = await api.email.sendEmailVerifyCode({
|
||||
email: formik.values.email,
|
||||
email: hookForm.getValues('email'),
|
||||
scene: EmailVerifyCodeScene.forgetPassword,
|
||||
})
|
||||
formik.setFieldValue('token', res.data.token)
|
||||
formik.setFieldValue('userId', res.data.userId)
|
||||
hookForm.setValue('token', res.data.token)
|
||||
hookForm.setValue('userId', res.data.userId || '')
|
||||
} catch (err) {
|
||||
setCountdown(0)
|
||||
}
|
||||
@ -77,14 +75,14 @@ export default function ForgetPassword() {
|
||||
container
|
||||
component="form"
|
||||
spacing={[2, 1]}
|
||||
onSubmit={formik.handleSubmit}
|
||||
onSubmit={hookForm.handleSubmit(onSubmit)}
|
||||
>
|
||||
<Grid xs={12}>
|
||||
<TextField
|
||||
{...formik.getFieldProps('email')}
|
||||
{...hookForm.register('email')}
|
||||
required
|
||||
error={formik.touched.email && !!formik.errors.email}
|
||||
helperText={(formik.touched.email && formik.errors.email) || ' '}
|
||||
error={!!hookForm.formState.errors.email}
|
||||
helperText={hookForm.formState.errors.email?.message || ' '}
|
||||
fullWidth
|
||||
label="邮箱"
|
||||
autoComplete="email"
|
||||
@ -94,15 +92,12 @@ export default function ForgetPassword() {
|
||||
</Grid>
|
||||
<Grid xs={8}>
|
||||
<TextField
|
||||
{...formik.getFieldProps('verifyCode')}
|
||||
{...hookForm.register('verifyCode')}
|
||||
required
|
||||
error={formik.touched.verifyCode && !!formik.errors.verifyCode}
|
||||
helperText={
|
||||
(formik.touched.verifyCode && formik.errors.verifyCode) || ' '
|
||||
}
|
||||
error={!!hookForm.formState.errors.verifyCode}
|
||||
helperText={hookForm.formState.errors.verifyCode?.message || ' '}
|
||||
fullWidth
|
||||
label="验证码"
|
||||
autoComplete="verifyCode"
|
||||
/>
|
||||
</Grid>
|
||||
<Grid xs={4} mt={1}>
|
||||
@ -118,12 +113,10 @@ export default function ForgetPassword() {
|
||||
</Grid>
|
||||
<Grid xs={12}>
|
||||
<TextField
|
||||
{...formik.getFieldProps('password')}
|
||||
{...hookForm.register('password')}
|
||||
required
|
||||
error={formik.touched.password && !!formik.errors.password}
|
||||
helperText={
|
||||
(formik.touched.password && formik.errors.password) || ' '
|
||||
}
|
||||
error={!!hookForm.formState.errors.password}
|
||||
helperText={hookForm.formState.errors.password?.message || ' '}
|
||||
fullWidth
|
||||
label="新密码"
|
||||
type="password"
|
||||
|
@ -7,29 +7,34 @@ import Box from '@mui/material/Box'
|
||||
import LoginIcon from '@mui/icons-material/Login'
|
||||
import Typography from '@mui/material/Typography'
|
||||
import Container from '@mui/material/Container'
|
||||
import { useFormik } from 'formik'
|
||||
import { useRouter } from 'next/router'
|
||||
import * as yup from '@/utils/validation'
|
||||
import * as api from '@/api'
|
||||
import { LoginInputDto } from '@/api/user.interface'
|
||||
import { useForm, SubmitHandler } from 'react-hook-form'
|
||||
import { yupResolver } from '@hookform/resolvers/yup'
|
||||
|
||||
export default function Login() {
|
||||
const router = useRouter()
|
||||
|
||||
const formik = useFormik({
|
||||
initialValues: {
|
||||
const hookForm = useForm<LoginInputDto>({
|
||||
mode: 'onTouched',
|
||||
defaultValues: {
|
||||
email: '',
|
||||
password: '',
|
||||
},
|
||||
validationSchema: yup.object({
|
||||
email: yup.emailSchema,
|
||||
password: yup.string().required('请输入密码'),
|
||||
}),
|
||||
onSubmit: async (values) => {
|
||||
const res = await api.user.login(values)
|
||||
localStorage.setItem('accessToken', res.data)
|
||||
router.push('/')
|
||||
},
|
||||
resolver: yupResolver(
|
||||
yup.object({
|
||||
email: yup.emailSchema,
|
||||
password: yup.string().required('请输入密码'),
|
||||
}),
|
||||
),
|
||||
})
|
||||
const onSubmit: SubmitHandler<LoginInputDto> = async (values) => {
|
||||
const res = await api.user.login(values)
|
||||
localStorage.setItem('accessToken', res.data)
|
||||
router.push('/')
|
||||
}
|
||||
|
||||
return (
|
||||
<Container
|
||||
@ -48,12 +53,12 @@ export default function Login() {
|
||||
<Typography component="h1" variant="h5" mt={1} mb={3}>
|
||||
登录
|
||||
</Typography>
|
||||
<Box component="form" onSubmit={formik.handleSubmit}>
|
||||
<Box component="form" onSubmit={hookForm.handleSubmit(onSubmit)}>
|
||||
<TextField
|
||||
{...formik.getFieldProps('email')}
|
||||
{...hookForm.register('email')}
|
||||
required
|
||||
error={formik.touched.email && !!formik.errors.email}
|
||||
helperText={(formik.touched.email && formik.errors.email) || ' '}
|
||||
error={!!hookForm.formState.errors.email}
|
||||
helperText={hookForm.formState.errors.email?.message || ' '}
|
||||
fullWidth
|
||||
label="邮箱"
|
||||
autoComplete="email"
|
||||
@ -61,12 +66,10 @@ export default function Login() {
|
||||
sx={{ mt: 1 }}
|
||||
/>
|
||||
<TextField
|
||||
{...formik.getFieldProps('password')}
|
||||
{...hookForm.register('password')}
|
||||
required
|
||||
error={formik.touched.password && !!formik.errors.password}
|
||||
helperText={
|
||||
(formik.touched.password && formik.errors.password) || ' '
|
||||
}
|
||||
error={!!hookForm.formState.errors.password}
|
||||
helperText={hookForm.formState.errors.password?.message || ' '}
|
||||
fullWidth
|
||||
label="密码"
|
||||
type="password"
|
||||
|
@ -6,46 +6,45 @@ import Grid from '@mui/material/Unstable_Grid2'
|
||||
import AppRegistrationIcon from '@mui/icons-material/AppRegistration'
|
||||
import Typography from '@mui/material/Typography'
|
||||
import Container from '@mui/material/Container'
|
||||
import { useFormik } from 'formik'
|
||||
import { useRouter } from 'next/router'
|
||||
import * as yup from '@/utils/validation'
|
||||
import * as api from '@/api'
|
||||
import { RegisterInputDto } from '@/api/user.interface'
|
||||
import { EmailVerifyCodeScene } from '@/api/email.interface'
|
||||
import { useCountdown, COUNTDOWN_SECONDS } from '@/utils/useCountdown'
|
||||
import { useForm, SubmitHandler } from 'react-hook-form'
|
||||
import { yupResolver } from '@hookform/resolvers/yup'
|
||||
|
||||
export default function Register() {
|
||||
const router = useRouter()
|
||||
const { countdown, setCountdown } = useCountdown()
|
||||
|
||||
const formik = useFormik<RegisterInputDto>({
|
||||
initialValues: {
|
||||
email: '',
|
||||
password: '',
|
||||
verifyCode: '',
|
||||
token: '',
|
||||
},
|
||||
validationSchema: yup.object({
|
||||
email: yup.emailSchema,
|
||||
password: yup.passwordSchema,
|
||||
verifyCode: yup.verifyCodeSchema,
|
||||
}),
|
||||
onSubmit: async (values) => {
|
||||
const res = await api.user.register(values)
|
||||
localStorage.setItem('accessToken', res.data)
|
||||
router.push('/')
|
||||
},
|
||||
const hookForm = useForm<RegisterInputDto>({
|
||||
mode: 'onTouched',
|
||||
resolver: yupResolver(
|
||||
yup.object({
|
||||
email: yup.emailSchema,
|
||||
password: yup.passwordSchema,
|
||||
verifyCode: yup.verifyCodeSchema,
|
||||
}),
|
||||
),
|
||||
})
|
||||
const onSubmit: SubmitHandler<RegisterInputDto> = async (values) => {
|
||||
const res = await api.user.register(values)
|
||||
localStorage.setItem('accessToken', res.data)
|
||||
router.push('/')
|
||||
}
|
||||
|
||||
async function sendVerifyCode() {
|
||||
await formik.validateField('email')
|
||||
const isValid = await hookForm.trigger('email')
|
||||
if (!isValid) return
|
||||
setCountdown(COUNTDOWN_SECONDS)
|
||||
try {
|
||||
const res = await api.email.sendEmailVerifyCode({
|
||||
email: formik.values.email,
|
||||
email: hookForm.getValues('email'),
|
||||
scene: EmailVerifyCodeScene.register,
|
||||
})
|
||||
formik.setFieldValue('token', res.data.token)
|
||||
hookForm.setValue('token', res.data.token)
|
||||
} catch (err) {
|
||||
setCountdown(0)
|
||||
}
|
||||
@ -72,14 +71,14 @@ export default function Register() {
|
||||
container
|
||||
component="form"
|
||||
spacing={[2, 1]}
|
||||
onSubmit={formik.handleSubmit}
|
||||
onSubmit={hookForm.handleSubmit(onSubmit)}
|
||||
>
|
||||
<Grid xs={12}>
|
||||
<TextField
|
||||
{...formik.getFieldProps('email')}
|
||||
{...hookForm.register('email')}
|
||||
required
|
||||
error={formik.touched.email && !!formik.errors.email}
|
||||
helperText={(formik.touched.email && formik.errors.email) || ' '}
|
||||
error={!!hookForm.formState.errors.email}
|
||||
helperText={hookForm.formState.errors.email?.message || ' '}
|
||||
fullWidth
|
||||
label="邮箱"
|
||||
autoComplete="email"
|
||||
@ -89,15 +88,12 @@ export default function Register() {
|
||||
</Grid>
|
||||
<Grid xs={8}>
|
||||
<TextField
|
||||
{...formik.getFieldProps('verifyCode')}
|
||||
{...hookForm.register('verifyCode')}
|
||||
required
|
||||
error={formik.touched.verifyCode && !!formik.errors.verifyCode}
|
||||
helperText={
|
||||
(formik.touched.verifyCode && formik.errors.verifyCode) || ' '
|
||||
}
|
||||
error={!!hookForm.formState.errors.verifyCode}
|
||||
helperText={hookForm.formState.errors.verifyCode?.message || ' '}
|
||||
fullWidth
|
||||
label="验证码"
|
||||
autoComplete="verifyCode"
|
||||
/>
|
||||
</Grid>
|
||||
<Grid xs={4} mt={1}>
|
||||
@ -113,14 +109,12 @@ export default function Register() {
|
||||
</Grid>
|
||||
<Grid xs={12}>
|
||||
<TextField
|
||||
{...formik.getFieldProps('password')}
|
||||
{...hookForm.register('password')}
|
||||
required
|
||||
error={formik.touched.password && !!formik.errors.password}
|
||||
helperText={
|
||||
(formik.touched.password && formik.errors.password) || ' '
|
||||
}
|
||||
error={!!hookForm.formState.errors.password}
|
||||
helperText={hookForm.formState.errors.password?.message || ' '}
|
||||
fullWidth
|
||||
label="新密码"
|
||||
label="密码"
|
||||
type="password"
|
||||
autoComplete="current-password"
|
||||
/>
|
||||
|
Loading…
Reference in New Issue
Block a user