文章目录

  • 一文讲清楚React Hooks
    • 一、什么是 React Hooks?
    • 二、常用基础 Hooks
      • 2.1 useState:状态管理
        • 基本用法
        • 特点
      • 2.2 useEffect:副作用处理
        • 基本用法
        • 依赖数组说明
      • 2.3 useContext:上下文共享
        • 基本用法
        • 特点
    • 三、其他常用 Hooks
      • 3.1 useReducer:复杂状态管理
      • 3.2 useCallback:记忆化回调函数
      • 3.3 useMemo:记忆化计算结果
      • 3.4 useRef:获取DOM元素与存储可变值
    • 四、其他实用 Hooks
    • 五、Hooks 使用规则

一文讲清楚React Hooks

一、什么是 React Hooks?

React Hooks 是 React 16.8 版本引入的新特性,它允许开发者在不编写类组件的情况下使用状态(state)和其他 React 特性(如生命周期、上下文等)。Hooks 的出现解决了类组件中存在的代码复用困难、逻辑分散、生命周期函数臃肿等问题,让函数组件拥有了与类组件同等的能力。

二、常用基础 Hooks

2.1 useState:状态管理

`useState` 是最基础的 Hook,用于在函数组件中添加状态管理。

基本用法
import { useState } from 'react';function Counter() {// 声明一个名为count的状态变量,初始值为0// setCount是更新count的函数const [count, setCount] = useState(0);return (<div><p>你点击了 {count}</p><button onClick={() => setCount(count + 1)}>点击我</button></div>);
}
特点
  • 返回值:返回一个数组,第一个元素是当前状态值,第二个元素是更新状态的函数
  • 状态更新
    • 调用更新函数会重新渲染组件
    • 状态更新是异步的,多次连续更新会被合并
    • 如果新状态依赖于旧状态,应使用函数形式:`setCount(prevCount => prevCount + 1)`
  • 初始化:初始值只在组件首次渲染时生效

2.2 useEffect:副作用处理

`useEffect` 用于处理组件中的副作用操作,如数据获取、订阅、DOM 操作等,相当于类组件中的 `componentDidMount`、`componentDidUpdate` 和 `componentWillUnmount` 的组合。

基本用法
import { useState, useEffect } from 'react';function UserProfile({ userId }) {const [user, setUser] = useState(null);// 副作用函数useEffect(() => {// 获取用户数据(副作用操作)const fetchUser = async () => {const response = await fetch(\`/api/users/\${userId}\`);const data = await response.json();setUser(data);};fetchUser();// 清理函数(可选)return () => {// 组件卸载或userId变化时执行,用于取消订阅、清除定时器等console.log('清理操作');};}, [userId]); // 依赖数组:只有userId变化时,才会重新执行副作用if (!user) return <div>Loading...</div>;return <div>{user.name}</div>;
}
依赖数组说明
  • 空数组 `[]`:副作用只在组件挂载时执行一次,清理函数在组件卸载时执行(类似 `componentDidMount` 和 `componentWillUnmount`)
  • 包含特定值 `[value1, value2]`:组件挂载时执行,且当数组中的值发生变化时重新执行(类似 `componentDidUpdate`)
  • 不提供依赖数组:每次组件渲染都会执行副作用

2.3 useContext:上下文共享

`useContext` 用于在函数组件中获取上下文(Context)的值,避免了通过 props 层层传递数据的麻烦。

基本用法
import { createContext, useContext } from 'react';// 1. 创建上下文
const ThemeContext = createContext('light');// 2. 提供上下文值
function App() {return (<ThemeContext.Provider value="dark"><ThemedComponent /></ThemeContext.Provider>);
}// 3. 消费上下文值
function ThemedComponent() {// 使用useContext获取上下文值const theme = useContext(ThemeContext);return <div>当前主题:{theme}</div>;
}
特点
  • 当 `ThemeContext.Provider` 的 `value` 发生变化时,所有使用 `useContext(ThemeContext)` 的组件都会重新渲染
  • `useContext` 接收一个上下文对象(由 `createContext` 创建),并返回该上下文的当前值

三、其他常用 Hooks

3.1 useReducer:复杂状态管理

`useReducer` 是 `useState` 的替代方案,适用于处理复杂状态逻辑或多个子值组成的状态对象。

import { useReducer } from 'react';// 1. 定义reducer函数:接收当前状态和动作,返回新状态
function todoReducer(state, action) {switch (action.type) {case 'ADD_TODO':return [...state, { id: Date.now(), text: action.text, done: false }];case 'TOGGLE_TODO':return state.map(todo =>todo.id === action.id ? { ...todo, done: !todo.done } : todo);default:return state;}
}function TodoList() {// 2. 使用useReducer:接收reducer和初始状态,返回当前状态和dispatch函数const [todos, dispatch] = useReducer(todoReducer, []);return (<div><button onClick={() => dispatch({ type: 'ADD_TODO', text: '新任务' })}>添加任务</button><ul>{todos.map(todo => (<likey={todo.id}style={{ textDecoration: todo.done ? 'line-through' : 'none' }}onClick={() => dispatch({ type: 'TOGGLE_TODO', id: todo.id })}>{todo.text}</li>))}</ul></div>);
}

3.2 useCallback:记忆化回调函数

`useCallback` 用于记忆化回调函数,避免在每次渲染时创建新的函数实例,从而优化子组件的性能(配合 `React.memo` 使用)。

import { useCallback, useState } from 'react';function Parent() {const [count, setCount] = useState(0);// 记忆化回调函数:只有当依赖项变化时,才会创建新的函数const handleClick = useCallback(() => {console.log('点击事件');}, []); // 空依赖数组:函数只会被创建一次return (<div><Child onClick={handleClick} /><button onClick={() => setCount(count + 1)}>计数:{count}</button></div>);
}// 使用React.memo优化子组件,避免不必要的重渲染
const Child = React.memo(({ onClick }) => {console.log('Child 渲染');return <button onClick={onClick}>点击我</button>;
});

3.3 useMemo:记忆化计算结果

`useMemo` 用于记忆化计算结果,避免在每次渲染时重复执行昂贵的计算。

import { useMemo, useState } from 'react';function ExpensiveCalculation({ numbers }) {// 记忆化计算结果:只有当numbers变化时,才会重新计算const sum = useMemo(() => {console.log('执行计算');return numbers.reduce((acc, num) => acc + num, 0);}, [numbers]); // 依赖数组return <div>总和:{sum}</div>;
}function App() {const [count, setCount] = useState(0);const [numbers] = useState([1, 2, 3, 4, 5]);return (<div><ExpensiveCalculation numbers={numbers} /><button onClick={() => setCount(count + 1)}>计数:{count}</button></div>);
}

3.4 useRef:获取DOM元素与存储可变值

`useRef` 主要有两个用途:获取DOM元素引用和存储不需要引起重渲染的可变值。

import { useRef, useState, useEffect } from 'react';function TextInputWithFocusButton() {// 1. 获取DOM元素引用const inputEl = useRef(null);// 2. 存储可变值(不会引起重渲染)const renderCount = useRef(0);const [text, setText] = useState('');useEffect(() => {renderCount.current += 1; // 修改ref的值不会触发重渲染});const focusInput = () => {// 通过current属性访问DOM元素inputEl.current.focus();};return (<div><inputref={inputEl}value={text}onChange={(e) => setText(e.target.value)}/><button onClick={focusInput}>聚焦输入框</button><p>渲染次数:{renderCount.current}</p></div>);
}

四、其他实用 Hooks

Hook用途说明
`useImperativeHandle`自定义暴露给父组件的实例值,配合 `forwardRef` 使用
`useLayoutEffect`与 `useEffect` 类似,但会在DOM更新后同步执行,可能阻塞浏览器绘制
`useDebugValue`在React DevTools中为自定义Hook添加标签,便于调试

五、Hooks 使用规则

为了确保 React 能够正确识别和管理 Hooks,必须遵守以下规则:

  1. 只能在函数组件或自定义 Hook 的顶层调用 Hooks
    • 不能在条件语句、循环、嵌套函数中调用 Hooks
    • 错误示例:
     function MyComponent() {if (condition) {const [count, setCount] = useState(0); // ❌ 不能在条件中调用}// ...}```

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/web/88254.shtml
繁体地址,请注明出处:http://hk.pswp.cn/web/88254.shtml
英文地址,请注明出处:http://en.pswp.cn/web/88254.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Apache http 强制 https

1. 修改一下文件配置 sudo nano /etc/apache2/sites-enabled/000-default.conf<VirtualHost *:80>ServerName hongweizhu.comServerAlias www.hongweizhu.comServerAdmin webmasterlocalhostDocumentRoot /var/www/html# 强制重定向到HTTPSRewriteEngine OnRewriteCond …

【读代码】GLM-4.1V-Thinking:开源多模态推理模型的创新实践

一、基本介绍 1.1 项目背景 GLM-4.1V-Thinking是清华大学KEG实验室推出的新一代开源视觉语言模型,基于GLM-4-9B-0414基础模型构建。该项目通过引入"思维范式"和强化学习课程采样(RLCS)技术,显著提升了模型在复杂任务中的推理能力。其创新点包括: 64k超长上下文…

从代码生成到智能运维的革命性变革

AI大模型重塑软件开发&#xff1a;从代码生成到智能运维的革命性变革 希望对大家有一定的帮助&#xff0c;进行参考 目录AI大模型重塑软件开发&#xff1a;从代码生成到智能运维的革命性变革 希望对大家有一定的帮助&#xff0c;进行参考一、范式转移&#xff1a;软件开发进入&…

豆包编写Java程序小试

今天下载了一本第四版电气工程师手册&#xff0c;非常棒的一本书&#xff0c;在给PDF添加目录的时候&#xff0c;由于目录有将近60页&#xff0c;使用老马开发的PdgCntEditor有点卡顿&#xff0c;不过补充下&#xff0c;老马这个PdgCntEditor还是非常好的。所以我决定用Java编一…

SpringBoot整合腾讯云新一代行为验证码

一 产品介绍 腾讯云官方介绍链接 腾讯云新一代行为验证码&#xff08;Captcha&#xff09;&#xff0c;基于十道安全防护策略&#xff0c;为网页、App、小程序开发者打造立体、全面的人机验证。在保护注册登录、活动秒杀、点赞发帖、数据保护等各大场景下业务安全的同时&…

SenseGlove新一代外骨骼力反馈手套Rembrand来袭!亚毫米级手部动捕+指尖触觉力采集+5Dof主动力反馈多模态

在远程机器人操作领域&#xff0c;精准的触觉感知与灵活的动作控制始终是核心需求。SenseGlove 新推出的 Rembrandt 力反馈外骨骼数据手套&#xff0c;以先进技术为支撑&#xff0c;为远程操控人形机器人手部提供了无缝解决方案&#xff0c;让操作更精准、更高效。值得一提的是…

Linux 信号机制:操作系统的“紧急电话”系统

想象一下&#xff0c;你正在电脑前专心工作&#xff0c;突然手机响了——这是一个通知&#xff0c;要求你立即处理一件新事情&#xff08;比如接电话&#xff09;。 Linux 系统中的信号&#xff08;Signal&#xff09;​​ 机制&#xff0c;本质上就是操作系统内核或进程之间用…

论文略读:Prefix-Tuning: Optimizing Continuous Prompts for Generation

2021 ACL固定预训练LM&#xff0c;为LM添加可训练&#xff0c;任务特定的前缀这样就可以为不同任务保存不同的前缀这种前缀可以看成连续可微的soft prompt&#xff0c;相比于离散的token&#xff0c;更好优化&#xff0c;效果更好训练的时候只需要更新prefix部分的参数&#xf…

CSS基础选择器、文本属性、引入方式及Chorme调试工具

CSS基础 1.1 CSS简介 CSS 是层叠样式表 ( Cascading Style Sheets ) 的简称. 有时我们也会称之为 CSS 样式表或级联样式表。 CSS 是也是一种标记语言 CSS 主要用于设置 HTML 页面中的文本内容&#xff08;字体、大小、对齐方式等&#xff09;、图片的外形&#xff08;宽高、边…

RabbitMQ 高级特性之事务

1. 简介与 MySQL、Redis 一样&#xff0c;RabbitMQ 也支持事务。事务中的消息&#xff0c;要么全都发送成功&#xff0c;要么全部发送失败&#xff0c;不会出现一部分成功一部分失败的情况。2. 使用事务发送消息spring 中使用 RabbitMQ 开启事务需要两步&#xff1a;第一步&…

iframe 的同源限制与反爬机制的冲突

一、事件背景A域名接入了动态防护&#xff08;Bot 防护、反爬虫机制&#xff09;&#xff0c;同时第三方业务B域名通过内嵌iframe的方式调用了A域名下的一个链接。二、动态防护介绍&#xff1a;动态防护&#xff08;也称为 Bot 防护、反爬虫机制&#xff09;是网站为了防止自动…

Rust 的 Copy 语义:深入浅出指南

在 Rust 中&#xff0c;Copy 是一个关键的特性&#xff0c;它定义了类型的复制行为。理解 Copy 语义对于掌握 Rust 的所有权系统和编写高效代码至关重要。一、核心概念&#xff1a;Copy vs Move特性Copy 类型非 Copy 类型 (Move)赋值行为按位复制 (bitwise copy)所有权转移 (ow…

Qt的信号与槽(二)

Qt的信号与槽&#xff08;二&#xff09;1.自定义槽2.通过图形化界面来生成自定义槽3.自定义信号3.信号和槽带参数4.参数数量5.connect函数的设计&#x1f31f;hello&#xff0c;各位读者大大们你们好呀&#x1f31f;&#x1f31f; &#x1f680;&#x1f680;系列专栏&#xf…

Java研学-MongoDB(三)

三 文档相关 7 文档统计查询① 语法&#xff1a; // 精确统计文档数 慢 准 dahuang> db.xiaohuang.countDocuments({条件}) 4 // 粗略统计文档数 快 大致准 dahuang> db.xiaohuang.estimatedDocumentCount({条件}) 4② 例子&#xff1a; // 精确统计文档数 name为奔波儿灞…

TCP协议格式与连接释放

TCP报文段格式 TCP虽然是面向字节流的&#xff0c;但TCP传送带数据单元确是报文段。TCP报文段分为首部和数据段部分&#xff0c;而TCP的全部功能体现在它在首部中各字段的作用。因此&#xff0c;只有弄清TCP首部各字段的作用才能掌握TCP的工作原理。 TCP报文段首部的前20字节是…

CSS05:结构伪类选择器和属性选择器

结构伪类选择器 /*ul的第一个子元素*/ ul li:first-child{background: #0af6f6; }/*ul的最后一个子元素*/ ul li:last-child{background: #d27bf3; } /*选中p1&#xff1a;定位到父元素&#xff0c;选择当前的第一个元素 选择当前p元素的父级元素&#xff0c;选中父级元素的第…

使用策略模式 + 自动注册机制来构建旅游点评系统的搜索模块

✅ 目标&#xff1a; 搜索模块支持不同内容类型&#xff08;攻略、达人、游记等&#xff09;每种搜索逻辑用一个策略类表示自动注册&#xff08;基于注解 Spring 容器&#xff09;新增搜索类型时&#xff0c;只需添加一个类 一个注解&#xff0c;无需改工厂、注册表等&#x…

第八十九篇 大数据开发中的数据算法:贪心策略 - 生活中的“精打细算”艺术

在资源有限的世界里&#xff0c;贪心算法教会我们&#xff1a;局部最优的累积&#xff0c;往往是通往全局最高效的捷径。本文通过3个生活化场景原创图表&#xff0c;揭示大数据开发中最实用的优化策略。目录一、贪心算法核心思想&#xff1a;当下即最优二、三大核心应用场景详解…

【论文阅读】Dynamic Few-Shot Visual Learning without Forgetting

系统概述如下: (a) 一个基于卷积神经网络(ConvNet)的识别模型,该模型包含特征提取器和分类器; (b) 一个少样本分类权重生成器。这两个组件都是在一组基础类别上训练的,我们为这些类别准备了大量训练数据。在测试阶段,权重生成器会接收少量新类别的训练数据以及基础类别的…

HTML应用指南:利用GET请求获取全国山姆门店位置信息

山姆会员店作为全球知名的零售品牌&#xff0c;自进入中国市场以来&#xff0c;始终致力于为消费者提供高品质商品与便捷的购物体验。随着新零售业态的快速发展&#xff0c;门店位置信息的获取变得愈发重要。品牌通过不断拓展门店网络&#xff0c;目前已覆盖多个一、二线城市&a…