定义:
除了使用内置的 Hooks 之外,还可以自定义 Hooks
自定义 Hooks 针对不同组件实现不同状态逻辑复用。
-
自定义 Hooks 是一个函数,约定函数名称必须以 use 开头,React 就是通过函数名称是否以 use 开头来判断是不是 Hooks
-
Hooks 只能在函数组件中或其他自定义 Hooks 中使用,否则,会报错!
-
自定义 Hooks 用来提取组件的状态逻辑,根据不同功能可以有不同的参数和返回值(就像使用普通函数一样)
使用场景:
将组件状态逻辑提取到可重用的函数(自定义 Hooks)中,实现状态逻辑复用。
封装一个倒计时-代码:
代码:
/* eslint-disable react-hooks/exhaustive-deps */
import { useState, useEffect, useRef } from 'react'
export default function useCountDown (initCount = 10, callBack = () => {}) {
const [count, setCount] = useState(initCount) // initCount 默认值 10s
const reftimerId = useRef(null)
// 调用这个方法,开始倒数
const start = () => {
setCount(initCount)
reftimerId.current = setInterval(() => {
setCount((count) => count - 1)
}, 1000)
}
useEffect(
() => {
console.log('观察count变了', count)
if (count === 0) {
// 执行回调
callBack()
// 清除定时器
clearInterval(reftimerId.current)
}
},
[count]
)
// 执行完一次后,count的值就变成了最后那个数,所以要再清除一下定时器
useEffect(() => {
return () => {
console.log('组件销毁,清空定时器')
// 清除定时器
clearInterval(reftimerId.current)
}
}, [])
return {
count, // 5 > 4 > 3 > 2 > 1 > 0
start // return出去开始倒数的方法,在其他页面调用satrt方法,完成倒计时
}
}
如何使用封装的倒计时?
需求:打开页面5s后 自动跳转到指定页面
import React, { useEffect } from 'react'
import ReactDOM from 'react-dom'
import useCountDown from './3.提炼hook'
export default function Time () {
const { count, start } = useCountDown(5, () => {
location.href = 'http://www.baidu.com'
})
useEffect(() => {
start(5)
}, [])
return (
<div>
你访问的页面不存在,{count}s后跳转到主页,或者点击<a href="http://www.baidu.com">这里</a>进行跳转
</div>
)
}
ReactDOM.render(<Time />, document.getElementById('root'))
需求:模拟手机验证码倒计时
代码:
/* eslint-disable react-hooks/exhaustive-deps */
import React, { useState } from 'react'
import ReactDOM from 'react-dom'
import useCountDown from './3.提炼hook'
export default function Time () {
const [canSend, setCanSend] = useState(true)
const { count, start } = useCountDown(10, () => {
setCanSend(true)
})
const hClick = () => {
// 1.按钮不可用
setCanSend(false)
// 2. 开始倒数
start()
}
return (
<div>
模拟手机验证码<br />
{/* {count} */}
<button disabled={!canSend} onClick={hClick}>
{canSend ? '发送验证码' : count + '秒再试'}
</button>
</div>
)
}
ReactDOM.render(<Time />, document.getElementById('root'))