自定义Hook大概是React Hooks最迷人的特性了。它让你能把组件里那些纠缠在一起的逻辑抽出来,变成一个独立、可复用的函数。这可不是什么高阶组件或者渲染属性那种绕弯子的复用,而是最直接的函数复用。
![图片[1]-如何自定义Hook?-速码派](http://www.sumapai.com/wp-content/uploads/2026/01/d752316edf0a4cf7ae578fd7bfe6ef14tplv-tb4s082cfz-aigc_resize_1080_1080-5-1024x683.webp)
自定义Hook是什么?
简单说,它就是一个普通的JavaScript函数,但名字必须以use开头,而且内部可以调用其他Hook(比如useState、useEffect)。React靠这个命名约定来检查你的Hook调用是否符合规则。
// 这不是一个组件,它不返回JSX。这是一个自定义Hook。
function useWindowWidth() {
const [width, setWidth] = useState(window.innerWidth);
useEffect(() => {
const handleResize = () => setWidth(window.innerWidth);
window.addEventListener('resize', handleResize);
return () => window.removeEventListener('resize', handleResize);
}, []);
return width;
}
这个useWindowWidth Hook封装了监听窗口大小和清理订阅的逻辑。任何组件需要用到当前窗口宽度时,直接调用它就行,不用再把一样的代码写一遍。
怎么从组件里抽逻辑?
想象你有个组件,里面有一堆处理表单状态的useState,还有验证逻辑。你发现另一个组件也需要差不多的东西。这时候就可以动手了:
- 新建一个
useForm.js文件。 - 把组件里所有和表单相关的状态、
useEffect、处理函数都剪贴过来。 - 把它们组织成一个函数,接收必要的初始参数(比如初始值),然后返回其他组件需要的东西(比如表单值、错误信息、提交函数)。
function useForm(initialValues) {
const [values, setValues] = useState(initialValues);
const handleChange = (e) => {
setValues({ ...values, [e.target.name]: e.target.value });
};
const resetForm = () => setValues(initialValues);
return { values, handleChange, resetForm };
}
在组件里用起来非常清爽:
function MyForm() {
const { values, handleChange, resetForm } = useForm({ name: '', email: '' });
return (
<form>
<input name="name" value={values.name} onChange={handleChange} />
<input name="email" value={values.email} onChange={handleChange} />
</form>
);
}
注意,每个组件调用同一个自定义Hook,得到的都是完全独立的状态和副作用。它们不会共享数据。你只是在复用逻辑,而不是状态本身。
什么时候该用?
别为了抽象而抽象。当你在两个以上的组件里发现了一模一样的Hook调用模式,或者某个组件内部的Hook逻辑已经复杂到影响阅读了,那就是抽成自定义Hook的好时机。常见的例子有:数据获取、订阅监听、动画逻辑、复杂的本地存储操作。
这就像是你给自己写了一套实用的工具函数库,只不过这些工具专门用来封装React的副作用和状态逻辑。用好了,代码会干净很多。























暂无评论内容