钩子 (Hooks) 的基础知识
什么是钩子?
在 React 中,钩子指的是可以在任何函数组件的顶层被调用的函数。在一个钩子中,您可以做到任何在组件中可以做的事,并返回任何数值 (或是不返回任何东西) 来满足您的需求。
信息
- 您可能在想通用函数 (util function) 和钩子之间有什么区别,因为「可以在任何函数组件的顶层被调用的函数」这句话听起来就像是在描述通用函数。一般来说,只要函数中使用了 React 才有的功能 (例如
useState()
或是useEffect()
),我们就会称它为钩子而不是普通的函数。 - 单纯从语法的角度来看,组件和钩子之间其实没有那么不同。事实上,若您在一个钩子中返回 JSX 元素,那就会让他变成一个组件而不是钩子!
范例
举例来说,如果我们有这样一个函数:
const useLogger = () => {
const log = (value) => {
console.log('[Logger]', value)
}
const warn = (value) => {
console.warn('[Logger]', value)
}
return {
log,
warn,
}
}
在上方的代码中,我们声明了一个 useLogger()
函数,他返回一个有着两个函数 log()
和 warn()
的物件。传统上,钩子的名称会以 use
开头。虽然这个函数并没有做任何特别的事情,但是他已经可以在组件中被作为钩子使用了!例如:
import { useLogger } from './UseLogger'
export const Example = () => {
const { log, warn } = useLogger()
return (
// ...
)
}
就像这样,您可以在钩子中设计自己的系统,并在任何组件中重复使用他。在钩子中,您可以随意声明变量和函数,依照需求更新他们,并选择要汇出 (返回) 哪些数值。返回的数值不一定要是物件;您可以返回一个数字、一个阵列、一个函数、甚至什么都不返回,一切都取决于您的设计。
React 提供许多内建的钩子供我们使用。您可以直接在组件中使用他们,或是使用他们来建构您自己的钩子。
注意事项
在钩子的帮助下,我们现在能够重复使用在整个应用程序中共享的功能,从而减少重复的代码。
然而,有一些重要的事情要记住:
- 在制作钩子时,重用性不是唯一需要考量的点。若某个组件的逻辑有点复杂,即使整个应用程序中只有一个组件在使用这个功能,将这个巨大的功能「切」(模组化) 成数个小功能 (钩子) 也是完全没问题的。如此一来,与将所有逻辑都放在同一个组件/钩子中相比,我们的代码将变得更容易阅读、维护及测试。
- 组件并不是唯一一个能够使用钩子的地方;您也可以在钩子中使用另外一个钩子!
- 更高的重用性不等于更好的代码!很多开发人员在面对新功能时会选择修改既有的钩子而不是制作一个新的,只为了让他能够在更多组件中被使用。在这种情况下,我们常常见到钩子「失控」— 为了能处理各种(边缘)情况,越来越多的参数和方法被加入,导致事情远比它应有的还要复杂;而且随着时间推移,重构/替换的成本只会越来越高。若您发现旧的钩子开始变得过于复杂,不要害怕建立新的钩子。