自定义 hooks 或者第三方 hooks,抽离公共部分,复用代码。
修改页面标题
tsx
import React, {useEffect} from 'react';
function useTitle(title) {
useEffect(() => {
document.title = title;
}, []);
}
export default useTitle;
获取鼠标位置
tsx
import React, {useEffect, useState} from 'react';
function useMouseMove() {
const [x, setX] = useState(0)
const [y, setY] = useState(0)
const handleMouseMove = (event) => {
setX(event.clientX)
setY(event.clientY)
}
useEffect(() => {
window.addEventListener('mousemove', handleMouseMove)
return () => {
window.removeEventListener('mousemove', handleMouseMove)
}
}, [x, y]);
return {x, y};
}
export default useMouseMove;
异步获取数据
tsx
import React, {useEffect, useState} from 'react';
function getInfo():Promise<string> {
return new Promise(resolve => {
setTimeout(() => {
resolve(Date.now().toString())
}, 1500)
})
}
function useGetInfo() {
const [loading, setLoading] = useState(true)
const [info, setInfo] = useState('')
useEffect(() => {
getInfo().then(info => {
setInfo(info)
setLoading(false)
})
}, []);
return { loading, info }
}
export default useGetInfo;
tsx
import useTitle from "./hooks/useTitle.tsx";
import useMouseMove from "./hooks/useMouseMove.tsx";
import useGetInfo from "./hooks/useGetInfo.tsx";
function App() {
useTitle('React Demo')
const {x, y} = useMouseMove()
const {loading, info} = useGetInfo()
return (
<>
<h1>React Demo</h1>
<div>鼠标位置:{x} {y}</div>
<div>异步获取当前时间:{loading ? '加载中' : info}</div>
</>
)
}
export default App
第三方 hooks
常见的有 ahooks 或者 react-use。
ahooks - React Hooks Library - ahooks 3.0
https://github.com/streamich/react-use
我们上面的 hooks 几乎在这些第三方库中都可以找到。
Hooks 规则
-
命名规则:
- Hook 必须
useXxx
格式来命名。
- Hook 必须
-
调用位置
- 组件内部
- 其他 Hook 内部
组件外部,或一个普通函数中,不能调用 Hook
-
顺序一致
Hook 必须是组件"第一层代码"
- Hook 不可放在 if 等条件语句中 ( 或者前面有 return ,也算是条件 )
- Hook 不可放在 for 等循环语句中
-
闭包陷阱
当异步函数中获取 state 时,可能不是最新的 state 值。
解决方案:替换为 useRef
------ 但 ref 变化不会触发 rerender ,所以得结合 state 一起。详情见:【React】React Hooks-CSDN博客