当前位置: 首页 > article >正文

大白话React Hooks(如 useState、useEffect)的使用方法与原理

啥是 React Hooks

在 React 里,以前我们写组件主要用类(class)的方式,写起来有点复杂,尤其是处理状态和副作用的时候。React Hooks 就是 React 16.8 之后推出的新特性,它能让我们不用写类,直接在函数组件里使用状态和其他 React 特性,让代码更简洁、更易复用。

useState 的使用方法与原理

使用方法

useState 就像是给函数组件装了个“小抽屉”,可以用来存放和管理状态。下面是一个简单的计数器示例:

import React, { useState } from'react';function Counter() {// 定义一个名为 count 的状态,初始值为 0// useState 返回一个数组,第一个元素是状态的值,第二个元素是更新这个状态的函数const [count, setCount] = useState(0);return (<div>{/* 显示 count 的值 */}<p>你点击了 {count} 次</p>{/* 点击按钮时调用 setCount 函数,将 count 的值加 1 */}<button onClick={() => setCount(count + 1)}>点击我</button></div>);
}export default Counter;

在这个例子里,我们用 useState 创建了一个状态 count,初始值是 0。每次点击按钮,就调用 setCount 函数来更新 count 的值。

原理

React 内部维护了一个状态链表。当我们调用 useState 时,React 会根据调用的顺序,从这个链表中取出对应位置的状态值。每次组件重新渲染,useState 都会按照相同的顺序从链表中获取状态。所以,useState 必须在组件的顶层调用,不能在条件判断、循环或者嵌套函数里调用,不然会打乱这个顺序,导致状态获取出错。

useEffect 的使用方法与原理

使用方法

useEffect 就像是组件的“小助手”,可以在组件渲染后执行一些额外的操作,比如数据获取、订阅事件、修改 DOM 等,这些操作就叫做副作用。下面是一个简单的数据获取示例:

import React, { useState, useEffect } from'react';function DataFetcher() {// 定义一个名为 data 的状态,初始值为 nullconst [data, setData] = useState(null);// 使用 useEffect 进行数据获取useEffect(() => {// 模拟一个异步的数据获取操作const fetchData = async () => {const response = await fetch('https://jsonplaceholder.typicode.com/todos/1');const result = await response.json();// 将获取到的数据更新到 data 状态中setData(result);};// 调用数据获取函数fetchData();// 可以返回一个清理函数,用于在组件卸载时执行一些清理操作,比如取消订阅等return () => {console.log('组件卸载了');};}, []); // 传入空数组,表示这个 useEffect 只在组件第一次渲染后执行return (<div>{data? (// 如果 data 不为 null,显示数据的标题<p>{data.title}</p>) : (// 如果 data 为 null,显示加载中<p>加载中...</p>)}</div>);
}export default DataFetcher;

在这个例子里,我们用 useEffect 模拟了一个数据获取的操作。useEffect 接收两个参数,第一个是一个回调函数,里面放着要执行的副作用操作;第二个是一个可选的数组,用于指定哪些值发生变化时才执行这个副作用。如果不传这个数组,副作用会在每次组件渲染后都执行;如果传一个空数组,副作用只会在组件第一次渲染后执行。

原理

React 会在组件渲染后记录下所有的 useEffect 回调函数。当组件重新渲染时,React 会先执行上一次 useEffect 返回的清理函数(如果有的话),然后再执行新的 useEffect 回调函数。通过传入的依赖数组,React 可以判断哪些 useEffect 需要重新执行。如果依赖数组里的值没有变化,对应的 useEffect 就不会重新执行,这样可以避免不必要的副作用操作,提高性能。

总结

useState 让函数组件可以有自己的状态,就像给组件装了个“小抽屉”来存放数据;useEffect 让函数组件可以在渲染后执行副作用操作,就像给组件请了个“小助手”来处理额外的事情。它们的原理都是基于 React 内部的机制,通过维护状态链表和记录副作用回调函数来实现相应的功能。

除了useState,React Hooks还有哪些常用的Hook?

除了 useState 外,React Hooks还有很多常用的Hook,以下是一些常见的Hook及其用法:

useEffect

  • 作用:相当于React类组件中的 componentDidMountcomponentDidUpdatecomponentWillUnmount 这几个生命周期函数的组合。可以用来处理一些副作用操作,像发送网络请求获取数据、添加订阅、操作DOM以及设置定时器等。
  • 举例:比如在一个新闻列表组件里,你可以用 useEffect 在组件加载后发送请求获取新闻数据,并且在组件卸载时清理相关资源,防止内存泄漏。

useContext

  • 作用:能让组件方便地获取到上下文(Context)中的数据,不用再通过一层一层地传递props这种麻烦的方式。适用于需要在多个组件之间共享数据,比如用户登录状态、主题设置等。
  • 举例:假如你的应用有一个全局的用户登录状态,很多组件都需要用到这个状态来判断是否显示某些内容,就可以用 useContext 让各个组件轻松获取到这个登录状态,而不用在每个组件的props里传来传去。

useReducer

  • 作用:和 useState 类似,也是用来管理状态的。不过它更适合用于管理复杂的状态逻辑,比如状态的更新依赖于之前的状态,或者有多个不同类型的状态更新操作。
  • 举例:在一个购物车应用里,管理购物车中商品的添加、删除、数量修改等复杂操作就可以用 useReducer,把这些操作的逻辑集中在一个地方处理,让代码更清晰。

useMemo

  • 作用:可以用来缓存一个值,这个值是通过某个函数计算出来的。只有当它的依赖项发生变化时,才会重新计算这个值,否则就直接使用缓存的值,这样能提高性能,避免一些不必要的计算。
  • 举例:在一个计算商品总价的组件里,如果商品列表很长,计算总价是个比较耗时的操作。用 useMemo 就可以在商品列表或价格等相关依赖项变化时才重新计算总价,其他时候直接用缓存的结果,加快组件的渲染速度。

useCallback

  • 作用:主要用于缓存函数,返回一个 memoized 回调函数。它可以确保在组件重新渲染时,如果依赖项没有变化,函数的引用就不会改变,这在将函数作为props传递给子组件,并且子组件依赖于函数的引用不变来进行优化时非常有用。
  • 举例:比如有一个父组件要把一个点击事件处理函数传递给子组件,用 useCallback 可以保证只要点击事件处理函数里用到的变量没有变化,这个函数的引用就不会变,这样子组件就不会因为父组件重新渲染而不必要地重新渲染。

useRef

  • 作用:可以用来创建一个对DOM元素或者组件实例的引用,也可以用来在组件的多次渲染之间保存一些可变的值,而且不会导致组件重新渲染。
  • 举例:在一个输入框组件里,你可以用 useRef 获取到输入框的DOM元素,方便进行聚焦、获取输入值等操作。还可以用它来保存一些临时的数据,比如保存上一次的某个状态值,在组件渲染时进行对比等。

除了上述Hook,React还有哪些不常用但很有用的Hook?

除了上述Hook外,React还有一些不常用但很有用的Hook,以下是几个典型的例子:

useLayoutEffect

  • 作用:和 useEffect 非常相似,也是用于处理副作用。但它的执行时机更特殊,是在所有的DOM变更都已经同步完成后,但在浏览器进行绘制之前执行。这使得它适合用于需要读取或操作DOM布局的场景,比如根据DOM元素的尺寸或位置来进行一些计算或调整。
  • 使用场景:当你需要根据组件的初始渲染或更新后的DOM布局来进行一些操作时,useLayoutEffect 就很有用。比如实现一个根据页面滚动位置来动态调整样式的粘性导航栏,需要在每次页面布局更新后立即获取滚动位置并进行样式调整,就可以用 useLayoutEffect

useImperativeHandle

  • 作用:通常用于在父组件中访问子组件的实例方法或属性。它可以让你自定义通过 ref 传递给父组件的内容,而不是直接暴露子组件的所有实例属性和方法,从而实现更精细的控制和封装。
  • 使用场景:在一些复杂的表单场景中,父组件可能需要调用子组件的特定方法来进行表单验证或获取表单数据。通过 useImperativeHandle,子组件可以将一些公共的、供父组件调用的方法暴露出来,而隐藏内部的实现细节。

useMutationEffect

  • 作用:这是一个实验性的Hook,用于在DOM发生变化时执行副作用。它的主要特点是可以更精细地控制副作用的执行时机,特别是在处理DOM突变相关的操作时更灵活。
  • 使用场景:当你需要对DOM的插入、删除或属性变化等操作进行更底层的监听和处理时,useMutationEffect 可能会派上用场。比如实现一个实时的DOM变化跟踪工具,用于记录页面上元素的添加、删除或属性修改等操作。

useDebugValue

  • 作用:主要用于在React开发者工具中显示自定义的调试信息,帮助开发者更好地理解组件的状态和行为。它可以为自定义的Hook添加一个标签,方便在调试时快速识别和查看Hook的相关数据。
  • 使用场景:在开发复杂的自定义Hook时,使用 useDebugValue 可以让你在开发者工具中为这个Hook显示更有意义的调试信息。比如你创建了一个用于处理用户权限的自定义Hook,通过 useDebugValue 可以显示当前用户的权限级别等信息,方便在调试时快速定位问题。

useDeferredValue

  • 作用:允许将某些状态更新延迟到更合适的时机进行处理,以提高应用的响应性。它可以将一个值标记为“可延迟”,这样当这个值发生变化时,不会立即触发组件的重新渲染,而是等到浏览器有空闲时间时再进行处理。
  • 使用场景:在处理一些非关键的、但可能会导致大量计算或渲染的状态更新时,useDeferredValue 很有帮助。比如在一个搜索结果列表中,用户输入搜索关键词时,你可以使用 useDeferredValue 来延迟更新搜索结果的渲染,直到用户停止输入一段时间后再进行更新,这样可以避免在用户快速输入时频繁地进行渲染,提高应用的流畅性。

相关文章:

大白话React Hooks(如 useState、useEffect)的使用方法与原理

啥是 React Hooks 在 React 里&#xff0c;以前我们写组件主要用类&#xff08;class&#xff09;的方式&#xff0c;写起来有点复杂&#xff0c;尤其是处理状态和副作用的时候。React Hooks 就是 React 16.8 之后推出的新特性&#xff0c;它能让我们不用写类&#xff0c;直接…...

【无标题】ABP更换MySql数据库

原因&#xff1a;ABP默认使用的数据库是sqlServer&#xff0c;本地没有安装sqlServer&#xff0c;安装的是mysql&#xff0c;需要更换数据库 ABP版本&#xff1a;9.0 此处以官网TodoApp项目为例 打开EntityFrameworkCore程序集&#xff0c;可以看到默认使用的是sqlServer&…...

掌握Git:从入门到精通的完整指南

Git是什么&#xff1f; Git是一个分布式版本控制系统&#xff0c;最初由Linus Torvalds在2005年为管理Linux内核开发而创建 它的主要功能是跟踪文件的更改&#xff0c;协调多个开发者之间的工作&#xff0c;并帮助团队高效地管理项目代码。Git不仅适用于大型开源项目&#xf…...

Windows上使用go-ios实现iOS17自动化

前言 在Windows上运行iOS的自动化&#xff0c;tidevice对于iOS17以上并不支持&#xff0c;原因是iOS 17 引入新通信协议 ‌RemoteXPCQUIC‌&#xff0c;改变了 XCUITest 的启动方式。 一、go-ios的安装 1、安装命令&#xff1a;npm i go-ios 2、安装完成后输入命令which io…...

服务器硬防的优势有哪些?

服务器硬防也可以称为硬件防火墙&#xff0c;是一种专门用来保护网络不会受到未经授权访问所设计的设备&#xff0c;硬件防火墙是一个独立的设备&#xff0c;同时也是集成在路由器或者是其它网络设备中的一部分&#xff0c;下面&#xff0c;小编就来为大家介绍一下服务器硬防的…...

Grok3使用体验与模型版本对比分析

文章目录 Grok的功能DeepSearch思考功能绘画功能Grok 3的独特功能 Grok 3的版本和特点与其他AI模型的比较 最新新闻&#xff1a;Grok3被誉为“地球上最聪明的AI” 最近&#xff0c;xAI公司正式发布了Grok3&#xff0c;并宣称其在多项基准测试中展现了惊艳的表现。据官方消息&am…...

JavaScript——前端基础3

目录 JavaScript简介 优点 可做的事情 运行 第一个JavaScript程序 搭建开发环境 安装的软件 操作 在浏览器中使用JavaScript文件 分离JS 使用node运行JS文件 语法 变量与常量 原生数据类型 模板字符串 字符串的内置方法 数组 对象 对象数组和JSON if条件语…...

零基础学习机器学习分类模型

下面将带你通过一个简单的机器学习项目&#xff0c;使用Python实现一个常见的分类问题。我们将使用著名的Iris数据集&#xff0c;来构建一个机器学习模型&#xff0c;进行花卉品种的分类。整个过程会包含&#xff1a; 原理介绍&#xff1a;机器学习的基本概念。数据加载和预处…...

Spring 源码硬核解析系列专题(十):Spring Data JPA 的 ORM 源码解析

在前几期中,我们从 Spring 核心到 Spring Boot、Spring Cloud、Spring Security 和 Spring Batch,逐步揭示了 Spring 生态的多样性。在企业级开发中,数据访问是不可或缺的部分,而 Spring Data JPA 通过简化 JPA(Java Persistence API)操作,成为主流的 ORM 框架。本篇将深…...

视频推拉流EasyDSS点播平台云端录像播放异常问题的排查与解决

EasyDSS视频直播点播平台是一个功能全面的系统&#xff0c;提供视频转码、点播、直播、视频推拉流以及H.265视频播放等一站式服务。该平台与RTMP高清摄像头配合使用&#xff0c;能够接收无人机设备的实时视频流&#xff0c;实现无人机视频推流直播和巡检等多种应用。 最近&…...

Oracle23版本 创建用户 报 00959和65096错误解决办法

00959错误解决办法&#xff0c;用户名必须已 c##或者C##开头 65096错误解决办法&#xff0c;创建用户名时去掉DEFAULT TABLESPACE smallrainTablespace这个属性 附上oracle 23版本创建表空间和用户语句&#xff1b; sqlplus sys as sysdba CREATE TABLESPACE smallrainOrac…...

Vue3 中 defineOptions 学习指南

在 Vue 3.3 及之后的版本中&#xff0c;defineOptions 是一个重要的宏&#xff08;macro&#xff09;&#xff0c;主要用于在 <script setup> 语法糖中声明组件的选项&#xff08;Options&#xff09;&#xff0c;解决了传统 <script setup> 无法直接定义组件选项的…...

简单说一下什么是RPC

部分内容来源&#xff1a;JavaGuide RPC是什么 RPC是远程调用 RPC的原理 RPC的五个部分 为了能够帮助小伙伴们理解 RPC 原理&#xff0c;我们可以将整个 RPC 的核心功能看作是下面 5 个部分实现的&#xff1a; 客户端&#xff08;服务消费端&#xff09;&#xff1a;调用…...

Pany-v2:LFI漏洞探测与敏感文件(私钥窃取/其他)自动探测工具

地址:https://github.com/MartinxMax/pany 关于Pany-v2 Pany-v2 是一款 LFI&#xff08;本地文件包含&#xff09;漏洞探测工具&#xff0c;具备自动识别敏感文件的能力。它能够利用 LFI 漏洞检测并提取 id_rsa 私钥、系统密码文件以及其他可能导致安全风险的敏感信息。该工具…...

北京大学DeepSeek与AIGC应用(PDF无套路下载)

近年来&#xff0c;人工智能技术飞速发展&#xff0c;尤其是大模型和生成式AI&#xff08;AIGC&#xff09;的突破&#xff0c;正在重塑各行各业的生产方式与创新路径。 北京大学联合DeepSeek团队推出的内部研讨教程《DeepSeek与AIGC应用》&#xff0c;以通俗易懂的方式系统解…...

AWS SDK for Java 1.x 403问题解决方法和原因

问题表现 使用AWS SDK for Java 1.x访问S3&#xff0c;已经确认文件存在&#xff0c;且具有权限&#xff0c;仍然出现403 Forbidden应答。 解决方法 升级到AWS SDK for Java 2.x。 问题原因 AWS签名机制严格依赖请求的精确路径格式&#xff0c;任何URI的差异&#xff08;如…...

Vue进阶之Vue2源码解析

Vue2源码解析 源码解析目录解析package.json入口查找入口文件确定vue入口this.\_init_ 方法$mount 挂载方法Vue.prototype._renderVue.prototype._updateVue.prototype._patch vue2 vue3 源码解析 目录解析 vue2.6之后的版本都做的是兼容Vue3的内容&#xff0c;2.6版本前的内…...

unity lua属性绑定刷新

我们现在有一个 角色属性类叫heroModel,内容如下,当heroModel中的等级发生变化的时候&#xff0c;我们需要刷新界面显示等级信息&#xff0c;通常我们是在收到等级升级成功的协议的时候&#xff0c;发送一个事件&#xff0c;UI界面接受到这个事件的时候&#xff0c;刷新一下等级…...

Ubuntu 下 nginx-1.24.0 源码分析 - ngx_conf_t

ngx_conf_t 定义在src/core/ngx_core.h typedef struct ngx_conf_s ngx_conf_t;ngx_conf_s 定义在 src/core/ngx_conf_file.h struct ngx_conf_s {char *name;ngx_array_t *args;ngx_cycle_t *cycle;ngx_pool_t *po…...

gtest 和 gmock讲解

Google Test&#xff08;gtest&#xff09;和 Google Mock&#xff08;gmock&#xff09;是 Google 开发的用于 C 的测试框架和模拟框架&#xff0c;以下是对它们的详细讲解&#xff1a; Google Test&#xff08;gtest&#xff09; 简介 Google Test 是一个用于 C 的单元测试框…...

Ubuntu20.04安装Redis

目录 切换到root用户 使用 apt install redis 安装redis 修改配置文件 ​编辑 重新启动服务器 使用Redis客户端连接服务器 切换到root用户 如果没有切换到root用户的&#xff0c;切换到root用户。 使用 apt install redis 安装redis 遇到y/n直接y即可。 redis安装好之…...

利用 DeepSeek 总结运维知识库的总结报告

一、背景 在运维工作中&#xff0c;知识库是重要的知识沉淀与共享工具。随着公司业务的发展&#xff0c;运维涉及的系统、设备和技术日益复杂&#xff0c;原有的运维知识库内容繁杂、缺乏条理&#xff0c;难以高效检索和利用。为了提升知识库的可用性&#xff0c;我尝试借助 D…...

Go基于协程池的延迟任务调度器

原理 通过用一个goroutine以及堆来存储要待调度的延迟任务&#xff0c;当达到调度时间后&#xff0c;将其添加到协程池中去执行。 主要是使用了chan、Mutex、atomic及ants协程池来实现。 用途 主要是用于高并发及大量定时任务要处理的情况&#xff0c;如果使用Go协程来实现每…...

一个原教旨的多路径 TCP

前面提到过 ECMP 和 TCP 之间的互不友好&#xff0c;pacing 收益和中断开销的互斥&#xff0c;在事实上阻碍了 packet-based LB 的部署&#xff0c;也限制了交换机&#xff0c;服务器的并发性能&#xff0c;同时潜在增加了 bufferbloat 的概率&#xff0c;而适用 packet-based …...

OSPF BIT 类型说明

注&#xff1a;本文为 “OSPF BIT 类型 | LSA 类型 ” 相关文章合辑。 机翻&#xff0c;未校。 15 OSPF BIT Types Explained 15 种 OSPF BIT 类型说明 Rashmi Bhardwaj Distribution of routing information within a single autonomous system in larger networks is per…...

如何获取mac os 安装盘

发现虚拟机VirtualBox支持Mac虚拟&#xff0c;就想尝试一下。但是发现Mac的安装盘特别难拿到&#xff0c;因此留档。 第一种方法 在mac环境下&#xff0c;使用softwareupdate命令来获取mac安装&#xff0c;能获得当前设备支持的系统。 使用这个命令&#xff1a;/usr/sbin/soft…...

【深度学习】强化学习(RL)-A3C(Asynchronous Advantage Actor-Critic)

A3C&#xff08;Asynchronous Advantage Actor-Critic&#xff09;详解 A3C&#xff08;Asynchronous Advantage Actor-Critic&#xff09; 是 深度强化学习&#xff08;Deep Reinforcement Learning, DRL&#xff09; 领域的重要算法&#xff0c;由 DeepMind 在 2016 年提出。…...

vue的双向绑定是怎么实现的

Vue.js 的双向绑定是通过 数据劫持&#xff08;Data Observation&#xff09; 和 发布-订阅模式&#xff08;Publish-Subscribe Pattern&#xff09; 实现的。具体来说&#xff0c;Vue 使用了以下核心技术&#xff1a; 数据劫持&#xff1a;通过 Object.defineProperty 或 Prox…...

在 Mac mini M2 上本地部署 DeepSeek-R1:14B:使用 Ollama 和 Chatbox 的完整指南

随着人工智能技术的飞速发展&#xff0c;本地部署大型语言模型&#xff08;LLM&#xff09;已成为许多技术爱好者的热门选择。本地部署不仅能够保护隐私&#xff0c;还能提供更灵活的使用体验。本文将详细介绍如何在 Mac mini M2&#xff08;24GB 内存&#xff09;上部署 DeepS…...

docker-compose部署onlyoffice8.3.0并支持ssl,且支持通过nginx代理,关闭JWT配置

编写docker-compose文件 mkdir -p /data/onlyoffice && echo "version: 3services:onlyoffice:container_name: OnlyOfficeimage: onlyoffice/documentserver:8.3.0restart: alwaysports:- 8088:80- 64431:443environment:TZ: Asia/ShanghaiJWT_ENABLED: falsevol…...