React 18中新钩子 useDeferredValue 使用

React是一个流行的用于构建用户界面的JavaScript库,它不断发展以为开发人员提供优化性能的工具。

React 18中引入的此类工具之一是useDeferredValue钩子,它旨在通过优先渲染更新来提高应用程序的性能。

useDeferredValue钩子是什么?

useDeferredValue钩子是React性能优化工具集中相对较新的补充。

它在处理异步数据获取(如网络请求或从API加载数据)时特别有用。

useDeferredValue的主要目的是,在立即呈现最重要的部分的同时,推迟对您的应用程序中不太关键的部分的更新。

这可以通过避免用户界面组件呈现延迟而大大提高应用程序的感知性能。

useDeferredValue的基本用法

useDeferredValue钩子的基本用法涉及包装状态值并创建其延迟版本。下面是一个简单的示例:

import { useState, useDeferredValue } from 'react';  

function MyComponent() {
  const [data, setData] = useState([]);
  const deferredData = useDeferredValue(data);   

  // ...
}

在这个例子中,我们有一个状态变量data,它可能会用异步操作填充数据。

通过使用useDeferredValue,我们创建了deferredData,这是data的一个版本,React 会单独优先渲染。

这种分离可确保您的 UI 中的关键部分及时更新,而非关键更新(如渲染列表)可以推迟以降低性能影响。

使用

首次渲染组件时,延迟值将与您传递的值相同。

更新组件时,延迟值将落后于最新值。这意味着 React 会首先使用旧的延迟值重新渲染组件,然后尝试在后台用新延迟值重新渲染它。

下面是一个例子,说明这在什么情况下有用:

想象一下,您有一个搜索栏,当您输入时会获取搜索结果。您开始输入“a”,React 使用加载后备项渲染搜索栏。“a”的搜索结果最终返回,React 使用结果重新渲染搜索栏。

// app.js
import { Suspense, useState } from 'react';
import SearchResults from './SearchResults.js';  

export default function App() {
  const [query, setQuery] = useState('');
  return (
    <>
      <label>  
        Search songs:
        <input value={query} onChange={e => setQuery(e.target.value)} />  
      </label>
      <Suspense fallback={<h2>Loading...</h2>}>
        <SearchResults query={query} />
      </Suspense>
    </>
  );
}
// searchResult.js
import { fetchData } from './data.js';
export default function SearchResults({ query }) {

    if (query === '') {
        return null;
    }
    const songs = use(fetchData(`/search?q=${query}`));

    if (songs.length === 0) {
        return <p>No matches for <i>"{query}"</i></p>;
    }
    return (
        <ul>
            {songs.map(song => (
                <li key={song.id}>  
                    {song.title} ({song.year})
                </li>
            ))}
        </ul>
    );
}  

function use(promise) {
    if (promise.status === 'fulfilled') {
        return promise.value;
    } else if (promise.status === 'rejected') {
        throw promise.reason;
    } else if (promise.status === 'pending') {
        throw promise;
    } else {
        promise.status = 'pending';
        promise.then(
            result => {
                promise.status = 'fulfilled';
                promise.value = result;
            },
            reason => {
                promise.status = 'rejected';
                promise.reason = reason;
            },
        );
        throw promise;
    }
}
// data.js

let cache = new Map();   

export function fetchData(url) {
    if (!cache.has(url)) {
        cache.set(url, getData(url));
    }
    return cache.get(url);
}  

async function getData(url) {
    if (url.startsWith('/search?q=')) {
        return await getSearchResults(url.slice('/search?q='.length));
    } else {
        throw Error('Not implemented');
    }
}

async function getSearchResults(query) {
    // Add a fake delay to make waiting noticeable.
    await new Promise(resolve => {
        setTimeout(resolve, 500);
    });

    const allSongs = [{
        id: 1,
        title: "Bohemian Rhapsody",
        year: 1975
    },
    {
        id: 2,  
        title: "Imagine",
        year: 1971
    },
    {
        id: 3,
        title: "Hotel California",
        year: 1976
    },
    {
        id: 4,
        title: "Stairway to Heaven",  
        year: 1971
    },
    {
        id: 5,
        title: "Let It Be",
        year: 1970
    },
    {
        id: 6,
        title: "Abbey",
        year: 1976
    },
    {
        id: 7,
        title: "A Hard Day's Night",
        year: 2012  
    }];

    const lowerQuery = query.trim().toLowerCase();
    return allSongs.filter(album => {
        const lowerTitle = album.title.toLowerCase();
        return (
            lowerTitle.startsWith(lowerQuery) || 
            lowerTitle.indexOf(' ' + lowerQuery) !== -1  
        )
    });
}

一种常用的替代UI模式涉及推迟更新结果列表并在新结果可用之前持久显示先前结果。

要实现这种方法,可以利用 useDeferredValue 钩子提供查询的延迟版本,因为它在组件层次结构中传播。

// app.js
import { Suspense, useState, useDeferredValue } from 'react';
import SearchResults from './searchResult.js';   

export default function App() {
  const [query, setQuery] = useState('');
  const deferredQuery = useDeferredValue(query);
  return ( 
    <>
      <label>
        Search Songs: 
        <input value={query} onChange={e => setQuery(e.target.value)} />
      </label>
      <Suspense fallback={<h2>Loading...</h2>}>
        <SearchResults query={deferredQuery} />   
      </Suspense>
    </>
  );  
}

现在,您将搜索查询编辑为“ab”。React 会首先使用旧的延迟值重新渲染搜索栏,即“a”的搜索结果。 然后,它会尝试使用新的延迟值重新渲染搜索栏,即“ab”的搜索结果。

这意味着用户不会再看到加载后备,即使“ab”的搜索结果需要很长时间才能返回。

换句话说,延迟值允许您立即渲染UI,即使您正在等待异步数据。 这可以通过避免不必要的加载后备来帮助提高用户体验。

useDeferredValue的好处

  1. 性能提升: 组件或数据的延迟加载和渲染可以导致更快的初始页面加载、降低资源使用和优化性能,从而带来更好的用户体验。

  2. 高效的资源利用: 通过按需加载所需内容,您可以减少不必要的 API 调用、最大限度地减少内存和 CPU 使用,并优化应用程序的资源利用。

  3. 渐进式加载和错误隔离: 延迟值策略支持渐进式加载以实现更高的响应性 UI,并提供更好的错误隔离,确保应用程序的一部分错误不会破坏整个用户体验。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【AI视野·今日Sound 声学论文速览 第四十四期】Tue, 9 Jan 2024

AI视野今日CS.Sound 声学论文速览 Tue, 9 Jan 2024 Totally 27 papers &#x1f449;上期速览✈更多精彩请移步主页 Daily Sound Papers DJCM: A Deep Joint Cascade Model for Singing Voice Separation and Vocal Pitch Estimation Authors Haojie Wei, Xueke Cao, Wenbo Xu…

PCIe进阶之Gen3 Physical Layer Transmit Logic(二)

1 文章概述 本文是接着上面一篇文章《Gen3 Physical Layer Transmit Logic(一)》继续对Gen3 Physical Layer Transmit Logic做进一步的解析,具体包含Byte Striping和Scrambling以及Serializer。 1.1 Byte Striping Gen3 x1 Ordered Set Construction如下所示: Ordered …

Vue入门五(Vue-CLI项目搭建|vue项目目录介绍|vue项目开发规范|es6导入导出语法)

文章目录 一、Vue-CLI 项目搭建介绍node环境搭建1) 下载与安装2&#xff09;测试是否安装成功 安装vue-cli安装vue脚手架 创建Vue项目1&#xff09;使用命令创建项目2&#xff09;使用图形化界面创建项目 二、vue项目目录介绍1.命令行运行vue项目2.Pycharm中运行项目3.目录结构…

k8s的策略

集群调度&#xff1a; Scheduler的调度算法&#xff1a; 预算策略 过滤出合适的节点 优先策略 选择部署的节点 NodeName&#xff1a;硬策略&#xff0c;不走调度策略&#xff0c;node1 nodeSelector&#xff1a;根据节点的标签选择&#xff0c;会走一个调度算法 只要是…

激活/注册navicat15

一、获取软件 链接&#xff1a;https://pan.baidu.com/s/1F_tiLuLvVFMEz8pDfIvDjw?pwdjjfj 提取码&#xff1a;jjfj 二、安装 安装的过程我就不放了&#xff0c;重点如下 安装完不要打开软件&#xff01; 安装完不要打开软件&#xff01; 安装完不要打开软件&#xff01;…

【阅读笔记】Chain of LoRA

一、论文信息 1 论文标题 Chain of LoRA: Efficient Fine-tuning of Language Models via Residual Learning 2 发表刊物 arXiv2023 3 作者团队 Department of Computer Science, Princeton University School of Computer Science and Engineering, Nanyang Technologic…

Unity获取系统语言

大家好&#xff0c;我是阿赵。   在使用Unity引擎做多语言的游戏时&#xff0c;很有可能需要根据用户的手机或者电脑的当前语言来设置游戏的默认语言。   Unity的API里面默认就有可以获取系统语言的方法&#xff1a; Application.systemLanguageUnity的API例子&#xff1a…

leetcode动态规划(零钱兑换II、组合总和 Ⅳ)

518.零钱兑换II 给定不同面额的硬币和一个总金额。写出函数来计算可以凑成总金额的硬币组合数。假设每一种面额的硬币有无限个。 示例 1: 输入: amount 5, coins [1, 2, 5] 输出: 4 解释: 有四种方式可以凑成总金额: 55 5221 52111 511111 示例 2: 输入: amount 3, coi…

R730服务器做了raid的硬盘,插在R720上面可以用吗?

环境 戴尔R720 戴尔R730 问题描述 R730服务器做了raid的硬盘&#xff0c;插在R720上面可以用吗&#xff1f; 解决方案 1.直接在 R730服务器做了raid的硬盘&#xff0c;卸下来在插在r720上面使用 &#xff0c;读不到硬盘 2.前往R730服务器上面&#xff0c;去清除RAID配置的…

数字化转型之路为何道阻且长?

数字化转型是企业在数字化时代下的整体转型&#xff0c;是一个系统、长期、艰巨的过程。其本质不仅仅是技术的升级&#xff0c;更多的是涉及业务流程&#xff0c;用数据来重构和升级企业的商业模式和运营模式。但为什么很多企业的数字化转型难以成功呢&#xff1f; 战略缺位&am…

Spring配置类以及扫描过程源码解析

书接上文 文章目录 一、 拾遗1. 回顾2. 源码分析 二、 配置类扫描源码分析1. 源码分析2. BeanDefinition覆盖问题3. full配置类和lite配置类的区别 一、 拾遗 1. 回顾 前面我们分析了Spring框架器启动过程要做的事情&#xff0c;着重分析了ApplicationContext的refresh方法。…

只有金蝶用户,才懂金蝶BI方案的含金量

资深金蝶系统用户都看得明明白白&#xff0c;金蝶系统侧重于企业资源的计划和管理&#xff0c;而当前企业数字化运营决策不仅需要高效合理的流程管理&#xff0c;更需要一套完善的数据分析方案&#xff08;金蝶BI方案&#xff09;&#xff0c;无缝对接金蝶系统&#xff0c;智能…

【Kafka-3.x-教程】-【五】Kafka-监控-Eagle

【Kafka-3.x-教程】专栏&#xff1a; 【Kafka-3.x-教程】-【一】Kafka 概述、Kafka 快速入门 【Kafka-3.x-教程】-【二】Kafka-生产者-Producer 【Kafka-3.x-教程】-【三】Kafka-Broker、Kafka-Kraft 【Kafka-3.x-教程】-【四】Kafka-消费者-Consumer 【Kafka-3.x-教程】-【五…

软件测试|Python如何将列表从大到小排序

简介 在编程中&#xff0c;对列表进行排序是一个常见的操作&#xff0c;有时候我们需要将列表按照从大到小的顺序进行排列。Python 提供了多种方法来实现这一目标。在本文中&#xff0c;我们将深入探讨几种将列表从大到小排序的方法&#xff0c;帮助您根据不同情况选择最合适的…

OpenHarmony—开发环境搭建

背景 因为没有实体的开发硬件&#xff0c;且不想破坏原有的Linux环境&#xff0c;所以这里基于 Docker QEMU 搭建开发环境 宿主机Linux系统命令行方式DockerQEMU 6.2 Docker环境准备 安装Docker 在Ubuntu中&#xff0c;可以使用下面的命令来安装Docker&#xff1a; sudo …

HarmonyOS自定义组件生命周期函数介绍

aboutToAppear 在创建自定义组件的新实例后&#xff0c;在执行其build()函数之前执行。允许在aboutToAppear函数中改变状态变量&#xff0c;更改将在后续执行build()函数中生效。 aboutToDisappear 在自定义组件析构销毁之前执行。不允许在aboutToDisappear函数中改变状态变…

SpringBoot怎么写一个自定义的starter,Gradle依赖引入starter的Jar包

1.新建一个Spring的项目myasset-spring-boot-starter 项目结构如下: 注意:不需要Application启动类 和 application.yml/application.properties文件 2. resources下添加spring.factories文件 # Auto Configure org.springframework.boot.autoconfigure.EnableAutoConfigu…

基于知识图谱的健康知识问答系统

基于知识图谱的健康知识问答系统 引言数据集与技术选型数据集技术选型 系统功能与实现数据导入与图数据库构建问答任务设计与实现1. 实体提取2. 用户意图识别 前端聊天界面与问答系统 结语 引言 随着互联网的发展&#xff0c;人们对健康知识的需求逐渐增加。为了更方便地获取健…

pytorch12:GPU加速模型训练

目录 1、CPU与GPU2、数据迁移至GPU2.1 to函数使用方法 3、torch.cuda常用方法4、多GPU并行运算4.1 torch.nn.DataParallel4.2 torch.distributed加速并行训练 5、gpu总结 1、CPU与GPU CPU&#xff08;Central Processing Unit, 中央处理器&#xff09;&#xff1a;主要包括控制…

【AIGC】一组精美动物AI智能画法秘诀

如何使用AI绘画&#xff0c;从以下角度&#xff0c;依据表格内容梳理&#xff0c;表格如下&#xff1a; 外貌特征物种姿势特征描述场景风格技术描述小巧可爱幼小浣熊倚在桌子上具有人形特征中世纪酒馆电影风格照明8k分辨率细节精致毛茸茸手持咖啡杯Jean-Baptiste Monge的风格蓝…