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

【React】useState 和 useRef:项目开发中该如何选择

如果你正踏入用 React 进行网页开发的世界,那你可能已经遇到了像 useStateuseRef 这样的术语。这两个 Hook 在构建交互性和动态组件时起着至关重要的作用。

下面,我们将探讨它们是什么,它们的功能,它们的区别,并通过一些易于理解的例子来具体说明应用场景。

useState: 反应式管理状态

当涉及到在函数式 React 组件中管理状态时,useState 就像是最有价值的球员(MVP)。它让你能够添加状态管理功能,使组件具有反应性并且视觉上可更新。

让我们看看这段小代码:

import React, { useState } from 'react';function Counter() {// 声明状态变量 'count' 和用于更新它的函数 'setCount'const [count, setCount] = useState(0);const increment = () => {// 使用 'setCount' 函数更新 'count' 状态setCount(count + 1);};// 渲染包含当前计数和一个递增按钮的 divreturn (<div><p>计数: {count}</p><button onClick={increment}>递增</button></div>);
} 

在这里,我们使用 useState(0) 声明了一个状态变量 count。点击“递增”按钮会更新状态并触发重新渲染。

那么当值重新渲染时会发生什么?

在重新渲染期间,状态保持其值,在渲染之间保持一致。React 高效地比较当前和前一状态以作出必要的更新。

useRef: 不触发重新渲染

不同于 useStateuseRef 在其值改变时不会触发重新渲染。这对于保持对 DOM 元素的持久引用或存储值而不立即产生视觉反应非常有用。

让我们通过一个输入框的例子来具体说明:

import React, { useRef, useEffect } from 'react';function AutoFocusInput() {// 创建一个存储输入元素的引用const inputRef = useRef();// `useEffect` 用于处理函数式组件中的副作用useEffect(() => {// 当组件挂载时聚焦输入元素// 空依赖数组确保它仅运行一次inputRef.current.focus();}, []);// 渲染带有引用的输入元素return <input ref={inputRef} />;
}

在这个例子中,useRef 创建了 inputRef,这是一个在渲染之间持久存在的引用。即使组件重新渲染,inputRef 也保持不变。

那么当值重新渲染时会发生什么?

在上面的例子中,inputRef 在重新渲染期间不受影响,即使组件发生变化也能保证稳定性。

那什么时候选择 useRef 而不是普通变量呢?

你可能会疑惑为什么使用 useRef 而不是普通的 let 变量?关键在于 useRef 的独特属性使其与众不同:

  • 渲染之间的持久性:与每次渲染都会被重新创建的 let 变量不同,useRef 在渲染之间保持其值,确保持久性。
  • 避免不必要的重新渲染:修改 let 变量,即使没有视觉变化,也可能触发不必要的重新渲染。useRef 通过不引起重新渲染来避免这种情况。

选择 useRef 在需要在渲染之间保持值并且避免不必要的重新渲染的情况下是一种更为高效的方法。

forwardRef: 在组件间共享引用

有时候,你需要从父组件向子组件传递一个引用。这时 forwardRef 就派上了用场,允许使用 useRef 将引用传递给子组件。

让我们看一个例子:

import React, { forwardRef, useRef, useImperativeHandle } from 'react';// 子组件
const ChildComponent = forwardRef((props, ref) => {// 声明一个内部引用变量用于输入元素const internalRef = useRef();// 使用 `useImperativeHandle` 向父组件暴露 focus 函数useImperativeHandle(ref, () => ({focus: () => {// 在内部引用上调用 focus 函数internalRef.current.focus();}}));// 渲染带有内部引用的输入元素return <input ref={internalRef} />;
});// 父组件
function ParentComponent() {// 在父组件中创建一个引用const childRef = useRef();// 在父组件中触发 focus 函数的函数const handleButtonClick = () => {childRef.current.focus();};return (<div>{/* 使用引用渲染子组件 */}<ChildComponent ref={childRef} />{/* 触发子组件中 focus 函数的按钮 */}<button onClick={handleButtonClick}>聚焦输入框</button></div>);
}

在这个例子中,forwardRef 从父组件 (ParentComponent) 向子组件 (ChildComponent) 传递一个引用,允许直接访问输入框的聚焦函数。

关键差异与选择合适的工具

  • useState: 适用于管理会触发组件重新渲染的状态。非常适合那些状态变化要求视觉更新的交互性和动态组件。
  • useRef: 对于维持对 DOM 元素的持久引用或存储值而不引起重新渲染非常有用。最适合直接操作 DOM 或者不希望触发重新渲染的情况。

记住,在同一个组件中可以同时使用这两个 Hook 来解决不同的需求。理解何时以及如何应用每一个 Hook 对有效的 React 开发至关重要。

总结来说…

如果你想更新数据并导致用户界面更新,那就选择 useState。如果需要在整个组件生命周期内更改数据而不触发不必要的渲染,那么 useRef 就是你的首选方案。

希望这篇文章能帮助你了解在 React 开发中 useStateuseRef 之间的区别。尝试在你的项目中运用这些概念,看看它们如何提升你的开发技能。

如果你有任何问题、建议或修正意见,请在评论区留言。

如果你想了解更多有关 React Hooks 的详细信息和示例,请查阅官方的 React 文档

相关文章:

【React】useState 和 useRef:项目开发中该如何选择

如果你正踏入用 React 进行网页开发的世界&#xff0c;那你可能已经遇到了像 useState 和 useRef 这样的术语。这两个 Hook 在构建交互性和动态组件时起着至关重要的作用。 下面&#xff0c;我们将探讨它们是什么&#xff0c;它们的功能&#xff0c;它们的区别&#xff0c;并通…...

python装饰器用法

为什么用装饰器&#xff1f; 第一个原因是&#xff0c;使用装饰器可以提升代码复用&#xff0c;避免重复冗余代码。如果我有多个函数需要测量执行时间&#xff0c;我可以直接将装饰器应用在这些函数上&#xff0c;而不是给多个函数加上一样的代码。这样的代码既元余也不方便后…...

AI 写作太死板?原因竟然是这个!

有些同学跟我埋怨说AI生成的文章太死板&#xff0c;一堆的“首先、其次、然后、再次、接着、总而言之……”&#xff0c;说话太官方&#xff0c;内容还很水。 想要让它模仿谁的语气&#xff0c;或者谁的文章&#xff0c;一点儿都不像。 名人都不模仿不了&#xff0c;更别说模…...

ansible实用模块

简介 ansible是基于 paramiko 开发的,并且基于模块化工作&#xff0c;本身没有批量部署的能力。真正具有批量部署的是ansible所运行的模块&#xff0c;ansible只是提供一种框架。ansible不需要在远程主机上安装client/agents&#xff0c;因为它们是基于ssh来和远程主机通讯的。…...

【JavaScript】JIT

JIT实际上指&#xff0c;JS的编译过程、运行时。 Just in Time 在传统的编译语言里&#xff0c;比如JAVA、Go等&#xff0c;是提前编译的&#xff0c;它们的执行是先在本地编译出一个"东西"&#xff0c;然后在放到服务器上运行。 提前编译的三大过程&#xff1a; …...

Matlab实现麻雀优化算法优化回声状态网络模型 (SSA-ESN)(附源码)

目录 1.内容介绍 2.部分代码 3.实验结果 4.内容获取 1内容介绍 麻雀搜索算法&#xff08;Sparrow Search Algorithm, SSA&#xff09;是一种新兴的群体智能优化算法&#xff0c;灵感来源于麻雀的觅食行为及其在面临危险时的预警机制。SSA通过模拟麻雀的这些自然行为来寻找问题…...

从 TCP Reno 经 BIC 到 CUBIC

重读 TCP拥塞控制算法-从BIC到CUBIC 以及 cubic 的 tcp friendliness 与拐点控制 这两篇文章&#xff0c;感觉还是啰嗦了&#xff0c;今日重新一气呵成这个话题。 reno 线性逼近管道容量 Wmax&#xff0c;相当于一次查询(capacity-seeking)&#xff0c;但长肥管道从 0.5*Wmax …...

工厂模式与建造者模式的区别

在软件设计中&#xff0c;工厂模式和建造者模式是两种常见的设计模式&#xff0c;它们都是用于创建对象&#xff0c;但是各自有不同的应用场景和目的。本文将通过餐馆点餐的例子&#xff0c;深入探讨这两种模式的区别。 工厂模式 工厂模式的核心思想是通过一个抽象工厂类来创…...

电脑usb接口封禁如何实现?5种禁用USB接口的方法分享!(第一种你GET了吗?)

“防患于未然&#xff0c;安全始于细节。”在信息技术飞速发展的今天&#xff0c;企业的信息安全问题日益凸显。 USB接口作为数据传输的重要通道&#xff0c;在带来便利的同时&#xff0c;也成为了数据泄露和安全风险的高发地。 因此&#xff0c;对电脑USB接口进行封闭管理&a…...

有效的括号

有效的括号 思路&#xff1a;我们先创建一个栈&#xff0c;让左括号入栈&#xff0c;与右括号判断 Stack stacknew Stack<>(); 将字符串中的符号转化为字符 char ch s.charAt(i); 完整代码如下&#xff1a; class Solution {public boolean isValid(String s) {if (s …...

Vue3.0面试题汇总

Composition API 可以说是Vue3的最大特点&#xff0c;那么为什么要推出Composition Api&#xff0c;解决了什么问题&#xff1f; 通常使用Vue2开发的项目&#xff0c;普遍会存在以下问题&#xff1a; 代码的可读性随着组件变大而变差每一种代码复用的方式&#xff0c;都存在缺…...

TCP编程:从入门到实践

目录 一、引言 二、TCP协议原理 1.面向连接 2.可靠传输 三、TCP编程实践 1.TCP服务器 2.TCP客户端 四、总结 本文将带你了解TCP编程的基本原理&#xff0c;并通过实战案例&#xff0c;教你如何在网络编程中运用TCP协议。掌握TCP编程&#xff0c;为构建稳定、高效的网络通信…...

Python NumPy 数据分析:处理复杂数据的高效方法

Python NumPy 数据分析&#xff1a;处理复杂数据的高效方法 文章目录 Python NumPy 数据分析&#xff1a;处理复杂数据的高效方法一 数据来源二 获取指定日期数据三 获取指定行列数据四 求和计算五 比例计算六 平均值和标准差七 完整代码示例八 源码地址 本文详细介绍了如何使用…...

【Preference Learning】Reasoning with Language Model is Planning with World Model

arxiv: https://arxiv.org/abs/2305.14992 问题背景&#xff1a;当前LLM推理受到几个关键因素的限制&#xff1a; &#xff08;1&#xff09;LLM缺乏世界模型&#xff08;一种人类就有的对环境的心理表征&#xff0c;可以模拟行动以及活动对外部世界状态的影响&#xff09;去…...

OJ在线评测系统 后端基础部分开发 完善CRUD相关接口

完善相关接口 判斷编程语言是否合法 先从用户的请求拿到Language package com.dduo.dduoj.service.impl;import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.dduo.dduoj…...

计算机网络--TCP、UDP抓包分析实验

计算机网络实验 目录 实验目的 实验环境 实验原理 1、UDP协议 2、TCP协议 实验具体步骤 实验目的 1、掌握使用wireshark工具对UDP协议进行抓包分析的方法&#xff0c;掌握UDP协议的报文格式&#xff0c;掌握UDP协议校验和的计算方法&#xff0c;理解UDP协议的优缺点&am…...

FreeRTOS的中断管理

前言 FreeRTOS的任务有优先级&#xff0c;MCU的硬件中断有中断优先级&#xff0c;这是两个不同的概念&#xff0c;FreeRTOS的任务管理要用到硬件中断&#xff0c;使用FreeRTOS时候也可以使用硬件中断&#xff0c;但是硬件中断ISR的设计要注意一些设计原则&#xff0c;在本节中我…...

JS加密=JS混淆?(JS加密、JS混淆,是一回事吗?)

JS加密、JS混淆&#xff0c;是一回事吗&#xff1f; 是的&#xff01;在国内&#xff0c;JS加密&#xff0c;其实就是指JS混淆。 1、当人们提起JS加密时&#xff0c;通常是指对JS代码进行混淆加密处理&#xff0c;而不是指JS加密算法&#xff08;如xor加密算法、md5加密算法、…...

hive-拉链表

目录 拉链表概述缓慢变化维拉链表定义 拉链表的实现常规拉链表历史数据每日新增数据历史数据与新增数据的合并 分区拉链表 拉链表概述 缓慢变化维 通常我们用一张维度表来维护维度信息&#xff0c;比如用户手机号码信息。然而随着时间的变化&#xff0c;某些用户信息会发生改…...

高并发内存池(六):补充内容

目录 有关大于256KB内存的申请和释放处理方法 处理大于256KB的内存申请 补充内容1 补充内容2 补充内容3 处理大于256KB的内存释放 新增内容1 新增内容2 测试函数 使用定长内存池替代new 释放对象时不传对象大小 补充内容1 补充内容2 补充内容3 补充内容4 测试…...

测试微信模版消息推送

进入“开发接口管理”--“公众平台测试账号”&#xff0c;无需申请公众账号、可在测试账号中体验并测试微信公众平台所有高级接口。 获取access_token: 自定义模版消息&#xff1a; 关注测试号&#xff1a;扫二维码关注测试号。 发送模版消息&#xff1a; import requests da…...

linux之kylin系统nginx的安装

一、nginx的作用 1.可做高性能的web服务器 直接处理静态资源&#xff08;HTML/CSS/图片等&#xff09;&#xff0c;响应速度远超传统服务器类似apache支持高并发连接 2.反向代理服务器 隐藏后端服务器IP地址&#xff0c;提高安全性 3.负载均衡服务器 支持多种策略分发流量…...

Qt/C++开发监控GB28181系统/取流协议/同时支持udp/tcp被动/tcp主动

一、前言说明 在2011版本的gb28181协议中&#xff0c;拉取视频流只要求udp方式&#xff0c;从2016开始要求新增支持tcp被动和tcp主动两种方式&#xff0c;udp理论上会丢包的&#xff0c;所以实际使用过程可能会出现画面花屏的情况&#xff0c;而tcp肯定不丢包&#xff0c;起码…...

Oracle查询表空间大小

1 查询数据库中所有的表空间以及表空间所占空间的大小 SELECTtablespace_name,sum( bytes ) / 1024 / 1024 FROMdba_data_files GROUP BYtablespace_name; 2 Oracle查询表空间大小及每个表所占空间的大小 SELECTtablespace_name,file_id,file_name,round( bytes / ( 1024 …...

SCAU期末笔记 - 数据分析与数据挖掘题库解析

这门怎么题库答案不全啊日 来简单学一下子来 一、选择题&#xff08;可多选&#xff09; 将原始数据进行集成、变换、维度规约、数值规约是在以下哪个步骤的任务?(C) A. 频繁模式挖掘 B.分类和预测 C.数据预处理 D.数据流挖掘 A. 频繁模式挖掘&#xff1a;专注于发现数据中…...

linux arm系统烧录

1、打开瑞芯微程序 2、按住linux arm 的 recover按键 插入电源 3、当瑞芯微检测到有设备 4、松开recover按键 5、选择升级固件 6、点击固件选择本地刷机的linux arm 镜像 7、点击升级 &#xff08;忘了有没有这步了 估计有&#xff09; 刷机程序 和 镜像 就不提供了。要刷的时…...

Java-41 深入浅出 Spring - 声明式事务的支持 事务配置 XML模式 XML+注解模式

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; &#x1f680; AI篇持续更新中&#xff01;&#xff08;长期更新&#xff09; 目前2025年06月05日更新到&#xff1a; AI炼丹日志-28 - Aud…...

【git】把本地更改提交远程新分支feature_g

创建并切换新分支 git checkout -b feature_g 添加并提交更改 git add . git commit -m “实现图片上传功能” 推送到远程 git push -u origin feature_g...

令牌桶 滑动窗口->限流 分布式信号量->限并发的原理 lua脚本分析介绍

文章目录 前言限流限制并发的实际理解限流令牌桶代码实现结果分析令牌桶lua的模拟实现原理总结&#xff1a; 滑动窗口代码实现结果分析lua脚本原理解析 限并发分布式信号量代码实现结果分析lua脚本实现原理 双注解去实现限流 并发结果分析&#xff1a; 实际业务去理解体会统一注…...

稳定币的深度剖析与展望

一、引言 在当今数字化浪潮席卷全球的时代&#xff0c;加密货币作为一种新兴的金融现象&#xff0c;正以前所未有的速度改变着我们对传统货币和金融体系的认知。然而&#xff0c;加密货币市场的高度波动性却成为了其广泛应用和普及的一大障碍。在这样的背景下&#xff0c;稳定…...