当前位置: 首页 > 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 测试…...

Granite TimeSeries FlowState R1多步预测效果展示:滚动预测与置信区间可视化

Granite TimeSeries FlowState R1多步预测效果展示&#xff1a;滚动预测与置信区间可视化 时间序列预测这事儿&#xff0c;听起来挺专业&#xff0c;但其实离我们很近。比如&#xff0c;你猜明天超市的牛奶会卖出去多少箱&#xff1f;下个月公司的电费大概是多少&#xff1f;或…...

Ubuntu22.04手动编译GCC12.2全流程解析与避坑指南

1. 为什么要手动编译GCC12.2&#xff1f; 在Ubuntu22.04系统中&#xff0c;默认的软件仓库可能不会立即提供最新版本的GCC编译器。虽然可以通过添加PPA源来安装较新版本&#xff0c;但手动编译安装GCC12.2能带来几个独特优势&#xff1a; 首先&#xff0c;你可以完全控制编译选…...

X-AnyLabeling v2.5.0 深度解析:交互式视觉-文本提示如何重塑通用视觉任务标注范式

1. 交互式视觉-文本提示&#xff1a;标注工具的革命性突破 想象一下这样的场景&#xff1a;你面对一张熙熙攘攘的街景照片&#xff0c;需要标注其中所有"戴帽子的行人"和"红色交通工具"。传统标注工具需要你手动框选每个目标&#xff0c;而X-AnyLabeling v…...

Agent-S深度解析:首个超越人类性能的智能体框架实战指南

Agent-S深度解析&#xff1a;首个超越人类性能的智能体框架实战指南 【免费下载链接】Agent-S Agent S: an open agentic framework that uses computers like a human 项目地址: https://gitcode.com/GitHub_Trending/ag/Agent-S Agent-S作为开源智能体框架&#xff0c…...

APIPOST 8.x 脚本循环调用接口实战:从踩坑到完美解决OA流程压测问题

APIPOST 8.x 脚本循环调用接口实战&#xff1a;从踩坑到完美解决OA流程压测问题 最近在排查某OA系统偶发的流程异常时&#xff0c;需要模拟真实用户操作进行压力测试。原本考虑使用Jmeter&#xff0c;但环境配置较为复杂&#xff0c;于是尝试了国产工具APIPOST。没想到这次探索…...

nli-distilroberta-base企业应用:内部知识库问答系统中的答案逻辑有效性过滤

nli-distilroberta-base企业应用&#xff1a;内部知识库问答系统中的答案逻辑有效性过滤 1. 项目概述 在当今企业知识管理领域&#xff0c;内部知识库问答系统已成为提升员工效率的关键工具。然而&#xff0c;这类系统常常面临一个核心挑战&#xff1a;如何确保返回答案的逻辑…...

DiffSynth Studio终极指南:如何快速上手开源AI视频生成框架

DiffSynth Studio终极指南&#xff1a;如何快速上手开源AI视频生成框架 【免费下载链接】DiffSynth-Studio DiffSynth Studio 是一个扩散引擎。我们重组了包括 Text Encoder、UNet、VAE 等在内的架构&#xff0c;保持了与开源社区模型的兼容性&#xff0c;同时提高了计算性能。…...

传感器数据分发CollatedTrajectoryBuilder

一、前言首先对前面的知识做一个回顾&#xff0c;从 node_main.cc 文件中开始;//根据配置文件&#xff0c;命令行参数与话题重映射&#xff0c;订阅默认话题开始一条轨迹 node.StartTrajectoryWithDefaultTopics(trajectory_options);---------------------- 在node.cc里面 // …...

HomeAssistantLibrary:ESP32/ESP8266嵌入式MQTT自动发现库

1. HomeAssistantLibrary&#xff08;HALib&#xff09;技术深度解析 HomeAssistantLibrary&#xff08;简称 HALib&#xff09;是一个专为 ESP8266 和 ESP32 微控制器设计的轻量级、模块化 C 库&#xff0c;其核心目标是 在嵌入式端原生实现 Home Assistant 的 MQTT 自动发现…...

Palantir的缺点

Palantir&#xff08;水晶球&#xff09;的“威力未在对等博弈中验证”及“在复杂人机环境中失效”的问题&#xff0c;本质是其技术逻辑与“对抗性、非理性、动态性”博弈场景的根本冲突——它擅长在“己方数据占优、对手无反制能力”的非对称场景中整合信息&#xff0c;但在“…...