在 React 16.8 之前,函数组件只是无状态组件。要向组件添加状态,我们需要将函数组件转换为基于类的组件。此外,函数组件没有操作组件生命周期事件的选项。为了在函数组件中启用状态和生命周期事件,React 引入了一个名为 Hooks 的新概念。
钩子是普通的 JavaScript 函数,可以访问使用/应用它的组件的状态和生命周期事件。一般来说,hooks 以 use 关键字开头。React 带有一些内置的钩子,并且还允许创建自定义钩子。
内置钩子
让我们知道 React 中可用的钩子列表及其基本用法。
- useState − 用于操作组件的状态。
- useReducer - 具有 reducer 概念的 useState 钩子的高级版本。
- useEffect - 用于挂接到组件的生命周期。
- useLayoutEffect - 类似于 useEffect,但在所有 DOM 突变之后或就在 DOM 将在屏幕上绘制之前同步触发。
- useContext - 提供对组件内部上下文提供程序的访问。
- useMemo - 用于返回变量/函数的记忆版本,该版本仅根据提供的预定义依赖项集进行更改。这将减少重新计算昂贵计算的次数,并提高应用程序的性能。
- useCallback - 返回回调函数的记忆版本,该版本仅根据提供的预定义依赖项集进行更改。
- useRef - 提供对基于React ref对象的原始DOM节点的访问。
- useImperativeHandle - 用于将子组件中基于 ref 的值公开给父组件。
- useDeferredValue - 用于延迟类似于去抖动或限制的值以延迟更新。
- useDebug - 用于在React DevTools中显示自定义钩子的标签。
- useTransition - 用于识别转换的挂起状态。
- useId - 用于为应用程序中的元素创建唯一ID。
应用钩子
让我们通过创建一个应用程序来学习如何在函数组件中使用钩子。
使用 create-react-app 创建一个 React 应用程序,并使用以下命令启动应用程序
create-react-app myapp
cd myapp
npm start
cd myapp
npm start
接下来,让我们创建一个新的函数组件 HelloWorld (src/components/HelloWorld.js),它呈现一个输入元素,并根据用户输入到输入元素中的数据呈现一条问候消息。
import { useState } from 'react';
export default function HelloWorld() {
const [name, setName] = useState("World")
return (
<div style={{ textAlign: "center", padding: "5px" }}>
<input id="name" name="name"
value={name}
onChange={(e) => setName(e.target.value)} />
<div>Hello {name}</div>
</div>
)
}
这里
- useState 是一个钩子,它接收一个初始值并返回一个状态和一个函数来更新状态。它接收 World 作为初始值,并返回一个包含两个项目的数组,a) 状态的初始值 (name) 和 b) 更新状态的函数 (setName)。使用的语法是数组销毁语法,用于获取数组值并将其设置为 name 和 setName 变量。
- input 是一个 react 输入元素,上面附加了一个 onChange 事件。onchange 事件:通过 event.target.value 获取用户的更新值,并使用 setName 函数将其设置为当前状态。
- 每当用户更新输入时,onchange 事件都会触发并更新状态,这反过来又会触发组件的渲染函数。
接下来,让我们在应用程序 (App.js) 中应用我们的组件,如下所示 -
import './App.css';
import HelloWorld from './components/HelloWorld';
function App() {
return (
<HelloWorld />
);
}
export default App;
最后,打开浏览器并通过更改输入值来检查结果。每当输入发生变化时,消息就会更新,如下所示 -

钩子的优点
当与 Hooks 一起使用时,函数组件与基于类的组件相比具有许多优点。它们如下 -
- 钩子很容易理解,并且可以快速开始编码。
- 在大型应用程序中,应用程序的复杂性可以保持在最低限度。在基于类的组件中,复杂性(状态管理和处理生命周期事件)随着项目的增长而增加。
- 对于JavaScript编程的初学者来说,这个在课堂上(组件)是很难理解的。由于函数组件和钩子不依赖于此,因此开发人员可以快速开始在 React 中编码,而无需陡峭的学习曲线。
- 有状态逻辑可以很容易地在组件之间重用。
- 功能组件可以与基于类的组件一起使用,这使得它很容易在任何规模的现有项目中采用。
- 与基于类的组件相比,函数组件可以编写的代码行数很少。
钩子的缺点
钩子是创建组件的替代方法,它也有其自身的缺点。它们如下 -
- 钩子应该只在顶层调用,并且应该避免在条件、循环或嵌套函数中调用。
- 钩子是专门的功能,它们可能不适合某些情况,我们可能必须恢复到基于类的组件。
- React 处理钩子的内部结构,而不暴露核心进行优化,这使得它的灵活性降低,不适合某些场景。
总结
钩子是创建组件的相对较新的方法。大量的项目仍在使用基于类的组件。将这些项目中的组件从基于类转换为基于函数实际上是不可能的,我们必须接受它。相反,我们可以分阶段转换应用程序。