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

news2025/3/3 4:33:51

啥是 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 的状态,初始值为 null
    const [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 来延迟更新搜索结果的渲染,直到用户停止输入一段时间后再进行更新,这样可以避免在用户快速输入时频繁地进行渲染,提高应用的流畅性。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

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

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

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…

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条件语…

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

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

简单说一下什么是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;以通俗易懂的方式系统解…

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;刷新一下等级…

Ubuntu20.04安装Redis

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

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…

【深度学习】强化学习(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 年提出。…

在 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…

【tplink】校园网接路由器如何单独登录自己的账号,wan-lan和lan-lan区别

老式路由器TPLINK&#xff0c;接入校园网后一人登录&#xff0c;所有人都能通过连接此路由器上网&#xff0c;无法解决遂上网搜索&#xff0c;无果&#xff0c;幸而偶然看到一个帖子说要把信号源网线接入路由器lan口&#xff0c;开启新世界。 一、wan-lan&#xff0c;lan-lan区…

DeepSeek开源周Day5压轴登场:3FS与Smallpond,能否终结AI数据瓶颈之争?

2025年2月28日&#xff0c;DeepSeek开源周迎来了第五天&#xff0c;也是本次活动的收官之日。自2月24日启动以来&#xff0c;DeepSeek团队以每天一个开源项目的节奏&#xff0c;陆续向全球开发者展示了他们在人工智能基础设施领域的最新成果。今天&#xff0c;他们发布了Fire-F…

[密码学实战]Java实现SM2数字信封(结合SM4对称加密)生成与解析

一、代码运行结果 二、什么是数字信封 2.1 基本概念 数字信封(Digital Envelope) 是一种结合对称加密与非对称加密的混合加密技术,通过以下步骤实现高效安全的数据传输: 对称加密:使用SM4算法加密原始数据,处理速度快,适合大数据量。非对称加密:使用SM2公钥加密SM4密…

Oracle 查询表空间使用情况及收缩数据文件

本文介绍Oracle收缩数据文件的相关操作&#xff0c;运维工作中有时会需要通过收缩数据文件来释放磁盘空间。 数据文件初始化方式&#xff1a; 1.我们创建表空间一般有两种方式初始化其数据文件&#xff0c;即指定初始大小为32G&#xff08;很大的值&#xff09;或指定初始大小为…

Grafana接入Zabbix数据源

1. 对接 Zabbix 1.1 安装 Zabbix 插件 在线安装&#xff1a; 1.2 配置 Zabbix 数据源 点击 Configuration > Data Sources > Add data source。选择 Zabbix&#xff0c;填写&#xff1a; URL&#xff1a;http://<zabbix-server>/api_jsonrpc.phpUsername&#x…