自定义hook
目的:状态逻辑复用。使用hook优势,逻辑复用、代码整洁,以及组织代码结构。
使用场景:
- 单一职责:每个 Hook 专注于一个特定功能(如数据获取、事件监听)。
- 命名清晰:使用
useXxx格式,明确 Hook 的用途(如useFetch,useLocalStorage)。- 复用逻辑:将组件间共用的逻辑抽离到 Hook 中,减少代码重复。
- 依赖管理:合理使用依赖数组(
useEffect的第二个参数),避免不必要的重渲染。
步骤:
- use开头
- 返回暴露状态或方法
注意事项
- 只能在函数组件或者hook中调用,不能在循环或条件语句中使用
案例:
- 获取窗口大小
useWindowSize
// useWindowSize.js
import { useState, useEffect } from 'react';
function useWindowSize() {
const [windowSize, setWindowSize] = useState({
width: window.innerWidth,
height: window.innerHeight,
});
useEffect(() => {
const handleResize = () => {
setWindowSize({
width: window.innerWidth,
height: window.innerHeight,
});
};
window.addEventListener('resize', handleResize);
return () => window.removeEventListener('resize', handleResize);
}, []);
return windowSize;
}
// 使用示例
function ResponsiveComponent() {
const { width, height } = useWindowSize();
return <div>Window Size: {width} x {height}</div>;
}
- 表单输入
// useFormInput.js
import { useState } from 'react';
function useFormInput(initialValue) {
const [value, setValue] = useState(initialValue);
const handleChange = (e) => {
setValue(e.target.value);
};
return {
value,
onChange: handleChange,
reset: () => setValue(initialValue),
};
}
// 使用示例
function LoginForm() {
const username = useFormInput('');
const password = useFormInput('');
return (
<form>
<input type="text" {...username} placeholder="Username" />
<input type="password" {...password} placeholder="Password" />
</form>
);
}
- Button防抖:添加loading状态
import {useState,useCallback,useRef} from 'react'
function useLock(asyncFn) {
const [loading, setLoading] = useState(false)
const asyncFnRef = useRef(null)
asyncFnRef.current = asyncFn
const run = useCallback(async (...args) => {
if(loading) return
setLoading(true)
try {
await asyncFnRef.current(...args)
} finally {
setLoading(false)
}
}, [loading])
return [loading,run]
}
//封装Button组件
import {Button as AntButton} from 'antd'
const Button = ({onClick,...props})=>{
const {loading, run} = useLock(onClick || (()=> {}))
return <AntButton loading={loading} {...props} onClick={run}></button>
}
//场景案例
const Demo = () => {
const handleSubmit = async () => {
// 模拟异步请求
await new Promise(resolve => setTimeout(resolve, 2000))
console.log('提交成功')
}
return (
<Button onClick={handleSubmit}>
提交
</Button>
)
}