目标
能够在点击获取验证码时显示倒计时
装自定义hooks
hooks/useCountDown.ts
import { useEffect, useRef, useState } from 'react'
export default function useCountDown (initCount = 10, callBack = () => {}) {
const timeId = useRef<{id:number}>({ id: 0 })
const [count, setCount] = useState(initCount)
const start = () => {
setCount(initCount)
timeId.current.id = window.setInterval(() => {
setCount((count) => count - 1)
}, 1000)
}
useEffect(() => {
return () => {
// console.log('..........')
clearInterval(timeId.current.id)
}
}, [])
useEffect(
() => {
// console.log(count, timeId.current)
if (count === 0) {
clearInterval(timeId.current.id)
callBack()
}
},
[count]
)
return { count, start }
}
使用自定义hooks
pages/Login/Login.tsx 中
+ import useCountDown from '@/hooks/useCountDown'
import { login, getCode } from '@/store/actions/login'
import { LoginForm } from '@/types/data'
import { Button, NavBar, Form, Input, List, Toast } from 'antd-mobile'
import { InputRef } from 'antd-mobile/es/components/input'
import { AxiosError } from 'axios'
import { useState, useRef } from 'react'
import { useDispatch } from 'react-redux'
import { useHistory } from 'react-router'
import styles from './index.module.scss'
const Login = () => {
+ const { count, start } = useCountDown(5, () => { setSentable(true) })
+ const [sendable, setSentable] = useState(true)
const [form] = Form.useForm()
const refMobile = useRef<InputRef>(null)
const dispatch = useDispatch()
const history = useHistory()
const onFinish = async (value: LoginForm) => {
try {
await dispatch(login(value))
// 登录成功提示
Toast.show({
content: '登录成功',
duration: 600,
afterClose: () => {
// 返回首页
history.push('/layout')
}
})
} catch (err) {
const error = err as AxiosError<{ message: string }>
Toast.show({
content: error.response?.data.message,
duration: 1000
})
}
}
const onGetCode = () => {
// 拿到手机号
const mobile = form.getFieldValue('mobile')
const errs = form.getFieldError('mobile')
if (errs.length) {
refMobile.current?.focus()
return
}
// 发验证码
dispatch(getCode(mobile))
// 禁用按钮
+ setSentable(false)
// 开始倒计时
+ start()
}
return (
<div className={styles.root}>
<NavBar />
<div className="login-form">
<h2 className="title">账号登录</h2>
<Form form={form} initialValues={{ mobile: 13811111111 }} onFinish={onFinish}>
<Form.Item
name="mobile"
className="login-item"
rules={[
{ required: true, message: '必须输入手机号' },
{ pattern: /^1\d{10}$/, message: '手机号格式不对' }
]}>
<Input ref={refMobile} placeholder="手机号" />
</Form.Item>
<List.Item
className="login-code-extra"
extra={
<span
className="code-extra"
+ onClick={sendable ? onGetCode : undefined}
+ >{sendable ? '发送验证码' : `${count}秒后重试`}
</span>
}>
<Form.Item
name="code"
className="login-item"
rules={[{ pattern: /^\d{6}$/, message: '必须输入6位数字的验证码' }]}>
<Input placeholder="请输入验证码" autoComplete="off" />
</Form.Item>
</List.Item>
<Form.Item noStyle>
<Button
block
type="submit"
color="primary"
className="login-submit">
提交
</Button>
</Form.Item>
</Form>
</div>
</div>
)
}
export default Login