- ReactJS 菜鸟教程
- ReactJS 教程
- ReactJS - 简介
- ReactJS - 安装
- ReactJS - 特性
- ReactJS - 优点和缺点
- ReactJS - 架构
- ReactJS - 创建 React 应用程序
- ReactJS - JSX
- ReactJS - 组件
- ReactJS - 嵌套组件
- ReactJS - 使用组件
- ReactJS - 组件集合
- ReactJS - 样式
- ReactJS - 属性(props)
- ReactJS - 使用属性创建组件
- ReactJS - props 验证
- ReactJS - 构造函数
- ReactJS - 组件生命周期
- ReactJS - 事件管理
- ReactJS - 创建事件感知组件
- ReactJS - 在Expense Manager APP中引入事件
- ReactJS - 状态管理
- ReactJS - 状态管理 API
- ReactJS - 无状态组件
- ReactJS - 使用 React Hooks 进行状态管理
- ReactJS - 使用 React 钩子的组件生命周期
- ReactJS - 组件的布局
- ReactJS - 分页
- ReactJS - Material 用户界面
- ReactJS - Http 客户端编程
- ReactJS - 表单编程
- ReactJS - 受控组件
- ReactJS - 不受控制的组件
- ReactJS - Formik
- ReactJS - 条件渲染
- ReactJS - 列表
- ReactJS - 键
- ReactJS - 路由
- ReactJS - 冗余
- ReactJS - 动画
- ReactJS - 引导程序
- ReactJS - 地图
- ReactJS - 表格
- ReactJS - 使用 Flux 管理状态
- ReactJS - 测试
- ReactJS - CLI 命令
- ReactJS - 构建和部署
- ReactJS - 示例
- ReactJS - 钩子简介
- ReactJS - 使用 useState
- ReactJS - 使用 useEffect
- ReactJS - 使用 useContext
- ReactJS - 使用 useRef
- ReactJS - 使用 useReducer
- ReactJS - 使用 useCallback
- ReactJS - 使用 useMemo
- ReactJS - 自定义钩子
- ReactJS - 可访问性
- ReactJS - 代码拆分
- ReactJS - 上下文
- ReactJS - 错误边界
- ReactJS - 转发引用
- ReactJS - 片段
- ReactJS - 高阶组件
- ReactJS - 与其他库集成
- ReactJS - 优化性能
- ReactJS - 分析器 API
- ReactJS - 门户
- ReactJS - 没有 ES6 ECMAScript 的 React
- ReactJS - 没有 JSX 的 React
- ReactJS - 协调
- ReactJS - 引用和 DOM
- ReactJS - 渲染属性
- ReactJS - 静态类型检查
- ReactJS - 严格模式
- ReactJS - Web 组件
- ReactJS - 日期选择器
- ReactJS - Helmet
- ReactJS - 内联样式
- ReactJS - 属性类型
- ReactJS - 浏览器路由器
- ReactJS - DOM
- ReactJS - 旋转木马
- ReactJS - 图标
- ReactJS - 表单组件
- ReactJS - 参考 API
ReactJS - 钩子简介
在 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 处理钩子的内部结构,而不暴露核心进行优化,这使得它的灵活性降低,不适合某些场景。
总结
钩子是创建组件的相对较新的方法。大量的项目仍在使用基于类的组件。将这些项目中的组件从基于类转换为基于函数实际上是不可能的,我们必须接受它。相反,我们可以分阶段转换应用程序。