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

React 中hooks之useDeferredValue用法总结

目录

  1. 概述
  2. 基本用法
  3. 与防抖节流的区别
  4. 使用场景
  5. 区分过时内容
  6. 最佳实践

概述

什么是 useDeferredValue?

useDeferredValue 是 React 18 引入的新 Hook,用于延迟更新某个不那么重要的部分。它接收一个值并返回该值的新副本,新副本会延迟更新。这种延迟是有益的,让紧急更新(如用户输入)优先于不紧急的更新(如渲染搜索结果列表)。

主要特点

  • 自动处理延迟
  • 与 Suspense 集成
  • 不会像防抖和useTransition那样丢弃中间值
  • 可以区分过时/最新内容

基本用法

1. 基本语法

import { useDeferredValue } from 'react';

function SearchResults() {
  const [query, setQuery] = useState('');
  const deferredQuery = useDeferredValue(query);
  
  return (
    <div>
      <input value={query} onChange={e => setQuery(e.target.value)} />
      <SlowList query={deferredQuery} /> {/* 使用延迟值进行渲染 */}
    </div>
  );
}

2. 区分过时内容示例

function SearchResults() {
  const [query, setQuery] = useState('');
  const deferredQuery = useDeferredValue(query);
  const isStale = query !== deferredQuery; // 判断内容是否过时
  
  return (
    <div>
      <input value={query} onChange={e => setQuery(e.target.value)} />
      <div style={{ 
        opacity: isStale ? 0.8 : 1,
        transition: 'opacity 0.2s ease'
      }}>
        <SlowList query={deferredQuery} />
      </div>
      {isStale && <div>Loading new results...</div>}
    </div>
  );
}

与防抖节流的区别

1. 防抖 (Debounce)

// 防抖示例
function SearchWithDebounce() {
  const [query, setQuery] = useState('');
  
  const debouncedSearch = useCallback(
    debounce((value) => {
      // 执行搜索
      performSearch(value);
    }, 500),
    []
  );
  
  // 会丢弃中间值,只处理最后一次输入
  return (
    <input 
      onChange={e => {
        setQuery(e.target.value);
        debouncedSearch(e.target.value);
      }} 
    />
  );
}

2. 节流 (Throttle)

// 节流示例
function SearchWithThrottle() {
  const [query, setQuery] = useState('');
  
  const throttledSearch = useCallback(
    throttle((value) => {
      performSearch(value);
    }, 100),
    []
  );
  
  // 固定时间间隔执行,可能会延迟响应
  return (
    <input 
      onChange={e => {
        setQuery(e.target.value);
        throttledSearch(e.target.value);
      }} 
    />
  );
}

3. useDeferredValue

// useDeferredValue 示例
function SearchWithDeferred() {
  const [query, setQuery] = useState('');
  const deferredQuery = useDeferredValue(query);
  
  // React 会根据用户设备性能和当前 CPU 负载自动调整延迟
  // 不会丢弃任何值,而是以较低优先级处理它们
  return (
    <>
      <input onChange={e => setQuery(e.target.value)} />
      <SlowList query={deferredQuery} />
    </>
  );
}

使用场景

1. 大列表渲染

function VirtualizedList({ items }) {
  const [filter, setFilter] = useState('');
  const deferredFilter = useDeferredValue(filter);
  const isStale = filter !== deferredFilter;
  
  const filteredItems = useMemo(
    () => items.filter(item => item.includes(deferredFilter)),
    [deferredFilter, items]
  );
  
  return (
    <div>
      <input value={filter} onChange={e => setFilter(e.target.value)} />
      <div style={{ opacity: isStale ? 0.8 : 1 }}>
        {filteredItems.map(item => (
          <ListItem key={item} item={item} />
        ))}
      </div>
    </div>
  );
}

2. 实时预览

function MarkdownEditor() {
  const [text, setText] = useState('');
  const deferredText = useDeferredValue(text);
  const isStale = text !== deferredText;
  
  return (
    <div className="editor">
      <textarea
        value={text}
        onChange={e => setText(e.target.value)}
      />
      <div className={`preview ${isStale ? 'stale' : ''}`}>
        <MarkdownPreview text={deferredText} />
      </div>
    </div>
  );
}

最佳实践

  1. 合理使用 useMemo
function SlowList({ text }) {
  const deferredText = useDeferredValue(text);
  const isStale = text !== deferredText;
  
  // 使用 useMemo 避免不必要的重新计算
  const items = useMemo(
    () => computeExpensiveList(deferredText),
    [deferredText]
  );
  
  return (
    <div style={{ opacity: isStale ? 0.8 : 1 }}>
      {items.map(item => (
        <ListItem key={item.id} item={item} />
      ))}
    </div>
  );
}
  1. 优雅降级处理
function SearchResults({ query }) {
  const deferredQuery = useDeferredValue(query);
  const isStale = query !== deferredQuery;
  
  return (
    <div>
      {isStale && (
        <div className="stale-indicator">
          Showing results for "{deferredQuery}"
          <br />
          Updating results for "{query}"...
        </div>
      )}
      <ResultsList query={deferredQuery} />
    </div>
  );
}

总结

  1. useDeferredValue vs 防抖/节流:

    • useDeferredValue 不会丢弃更新
    • 自动适应用户设备性能
    • 与 React 并发特性集成
    • 提供过时状态标识
  2. 适用场景:

    • 大数据列表渲染
    • 实时预览功能
    • 复杂图表更新
    • 搜索建议
  3. 最佳实践:

    • 配合 useMemo 使用
    • 提供加载状态反馈
    • 合理处理过时内容
    • 注意性能优化
      在这里插入图片描述

http://www.kler.cn/a/512050.html

相关文章:

  • SSE 实践:用 Vue 和 Spring Boot 实现实时数据传输
  • Spring Boot 3.3.4 升级导致 Logback 之前回滚策略配置不兼容问题解决
  • 解决leetcode第3426题所有安放棋子方案的曼哈顿距离
  • 【AI | pytorch】torch.view_as_complex的使用
  • Ubuntu 24.04 LTS 空闲硬盘挂载到 文件管理器的 other locations
  • “UniApp的音频播放——点击视频进入空白+解决视频播放器切换视频时一直加载的问题”——video.js、video-js.css
  • 深度学习 | 基于 LSTM 模型的多电池健康状态对比及预测
  • 【柱状图】——18
  • 【玩转全栈】----Django制作部门管理页面
  • 基于SpringBoot的智能家居系统的设计与实现(源码+SQL脚本+LW+部署讲解等)
  • XAMPP运行没有创建桌面图标
  • ChatGPT被曝存在爬虫漏洞,OpenAI未公开承认
  • 2025年美国大学生数学建模竞赛赛前准备计划
  • 【技术杂谈】Arcgis调用天地图和卫星影像
  • Spring Web MVC 探秘
  • Nginx location 和 proxy_pass 配置详解
  • 后端开发流程学习笔记
  • Linux 高级路由与流量控制-用 tc qdisc 管理 Linux 网络带宽
  • 【通信协议】TCP通信
  • 记录一个简单小需求,大屏组件的收缩与打开,无脑写法
  • 【日志篇】(7.6) ❀ 01. 在macOS下刷新FortiAnalyzer固件 ❀ FortiAnalyzer 日志分析
  • 【数据结构篇】顺序表 超详细!
  • AAAI2024论文解读|Towards Fairer Centroids in k-means Clustering面向更公平的 k 均值聚类中心
  • 【云原生布道系列】第三篇:“软”饭“硬”吃的计算
  • 在离线无管理员权限的情况下为Linux配置oh-my-zsh(zsh+oh my zsh+powerlevel10k)
  • 2025年免费量化交易软件——PTrade(含开通攻略)