新闻中心

在 React 中将 Promise 成功解析后的值赋给可变 ref 对象

2025-10-06
浏览次数:
返回列表

在 react 中将 promise 成功解析后的值赋给可变 ref 对象

本文旨在解决在 React 函数组件中使用 useRef 存储异步 API 请求结果,并避免每次渲染都重新发起请求的问题。我们将探讨如何利用 useRef 结合 async/await,有效地缓存 API 数据,提升应用性能,并提供详细的代码示例和注意事项。

在 React 应用中,我们经常需要从 API 获取数据并在组件中使用。为了避免不必要的 API 调用,我们希望在组件的生命周期内缓存 API 响应。useRef hook 提供了一种在组件重新渲染之间保持可变值的方式,非常适合用来缓存数据。然而,直接将 Promise 的结果赋值给 useRef 对象可能不会立即生效,导致访问到未更新的值。本文将介绍如何正确地使用 useRef 结合 async/await 来解决这个问题。

使用 useRef 缓存 API 数据

核心思路是创建一个函数,该函数首先检查 useRef 对象是否已经包含缓存的数据。如果存在,则直接返回缓存的数据;否则,调用 API 获取数据,将其存储到 useRef 对象中,并返回。

以下是一个具体的实现示例:

UXbot UXbot

AI产品设计工具

UXbot 185 查看详情 UXbot
import React, { useState, useEffect, useRef } from 'react';

// 假设的 API 请求函数
async function getMoviesRequest() {
  // 模拟 API 请求延迟
  await new Promise(resolve => setTimeout(resolve, 500));
  // 模拟返回电影数据
  return [
    { title: "Movie 1" },
    { title: "Movie 2" },
    { title: "Movie 3" },
    { title: "Movie 4" },
    { title: "Movie 5" },
    { title: "Movie 6" },
    { title: "Movie 7" },
    { title: "Movie 8" },
    { title: "Movie 9" },
    { title: "Movie 10" }
  ];
}

// 随机数生成函数
function getRandomInt(max) {
  return Math.floor(Math.random() * max);
}

export default function Page() {
  const cachedMoviesFromApi = useRef(null); // 初始化为 null
  const [movie, setMovie] = useState({ title: "" });

  useEffect(() => {
    setNewMovie().then(); // 确保在组件挂载后立即获取电影数据
  }, []);

  async function getMoviesFromCacheOrApi() {
    if (cachedMoviesFromApi.current) {
      console.log("从缓存中获取电影");
      return cachedMoviesFromApi.current;
    }

    console.log("从 API 获取电影");
    const moviesFromApi = await getMoviesRequest();
    cachedMoviesFromApi.current = moviesFromApi;

    return moviesFromApi;
  }

  async function setNewMovie() {
    const movies = await getMoviesFromCacheOrApi();
    const randomIndex = getRandomInt(9);
    const movie = movies[randomIndex];

    setMovie(movie);
  }

  return (
    <div>
      <h3>{movie.title}</h3>
      <button onClick={setNewMovie}>Generate New Movie</button>
    </div>
  );
}

代码解释:

  1. cachedMoviesFromApi: 使用 useRef(null) 创建一个 ref 对象,用于存储从 API 获取的电影数据。初始值为 null,表示尚未从 API 获取数据。
  2. getMoviesFromCacheOrApi: 这是一个异步函数,负责从缓存或 API 获取电影数据。
    • 首先检查 cachedMoviesFromApi.current 是否有值。如果有,则直接返回缓存的数据。
    • 如果缓存中没有数据,则调用 getMoviesRequest 函数从 API 获取数据。
    • 将获取到的数据赋值给 cachedMoviesFromApi.current,以便下次使用。
    • 最后返回从 API 获取的数据。
  3. setNewMovie: 这是一个异步函数,负责设置新的电影。
    • 调用 getMoviesFromCacheOrApi 函数获取电影数据(从缓存或 API)。
    • 随机选择一个电影。
    • 使用 setMovie 函数更新 movie state。
  4. useEffect: 在组件挂载后,调用 setNewMovie 函数,确保在组件加载时获取初始电影数据。

关键点:

  • async/await: 使用 async/await 确保 API 请求完成后再执行后续操作,避免访问到未定义的 movies 值。
  • null 初始化: cachedMoviesFromApi 初始化为 null,可以明确区分 "尚未加载" 和 "已加载,但数据为空" 的情况。 如果API可能返回空数组,则需要根据实际情况选择合适的初始值。
  • useEffect: 在 useEffect 中调用 setNewMovie().then() 确保异步操作完成。

注意事项

  • 错误处理: 在实际应用中,应该添加错误处理机制,例如使用 try...catch 块来捕获 API 请求可能发生的错误。
  • 缓存失效: 可以考虑添加缓存失效机制,例如设置一个缓存时间,定期从 API 重新获取数据。
  • 数据更新: 如果 API 数据会发生变化,需要考虑如何更新缓存。例如,可以添加一个 "刷新" 按钮,点击后强制从 API 重新获取数据。

总结

通过使用 useRef 结合 async/await,我们可以在 React 函数组件中有效地缓存 API 数据,避免不必要的 API 调用,提升应用性能。关键在于确保在访问 useRef 对象之前,API 请求已经完成,并且正确处理可能出现的错误。

以上就是在 React 中将 Promise 成功解析后的值赋给可变 ref 对象的详细内容,更多请关注其它相关文章!


# ai  # 加载  # 这是一个  # react  # 并在  # 寿光网络营销推广介绍  # 微商怎么推广营销tt吧技精  # 网站内部应该如何优化  # 凌海网站运营推广  # 剪映电商模版营销推广  # 黑龙江网站推广优化  # seo综合相信  # SEO竞价排名名词解释  # 广告视频网站新片场推广  # 随机数  # 有何不同  # 是一个  # 如何实现  # 服务端  # 有效地  # 自定义  # 安阳营销网站推广工具 


相关栏目: 【 科技资讯46185 】 【 网络学院92790


相关推荐: 痛风发作了怎么办? 快速止痛和后期饮食调理  蛙漫官方正版入口 蛙漫网页在线全集免费观看  必由学官网首页入口 必由学教师网页版登录指南  如何使用Go和Martini动态服务解码后的图片  邮政快递单号查询入口 邮政快递物流信息在线查询入口  PowerPoint如何制作滚动字幕结尾彩蛋_PowerPoint路径动画实现平滑滚动字幕效果  如何解决电商平台定制报价请求的“黑洞”问题,SprykerQuoteRequest模块助你提升客户体验与销售效率  Pandas DataFrame 多条件优先级排序与排名  PHP中获取MongoDB服务器运行时间(Uptime)的专业指南  小红书怎么解除第三方平台绑定_小红书多平台登录解绑方法介绍  在J*a中如何在J*a中使用异常机制记录错误日志_异常日志实践经验  J*a递归快速排序中静态变量的状态管理与陷阱  反效果?《战地6》免费试玩开启后玩家数不升反降  LINQ to XML为何解析失败? 深入理解C# XDocument的异常处理  抖音网页版快捷访问 抖音网页版网页版入口操作教程  Yandex搜索引擎一键访问入口_俄罗斯Yandex官网免登录  印象笔记如何设离线包出差查阅_印象笔记设离线包出差查阅【离线阅读】  漫蛙Manwa2官网入口地址分享 漫蛙漫画PC版永久访问通道  地铁跑酷免费秒玩入口链接 地铁跑酷小游戏免费秒玩网站  如何在网页中实现特定地点的随机图片展示  Spring Boot内嵌服务器与J*a EE全栈特性:选择与部署策略  jQuery Mask 插件中实现电话号码固定前导零的教程  字由网在线版登录地址 字由网网页版安全入口  从J*aScript对象中精确提取指定属性的教程  漫蛙2正版漫画站 漫蛙2网页版快速访问入口  生成rdflib自定义SPARQL函数:参数匹配与实践指南  Tabulator表格中精确实现日期时间排序的指南  126邮箱网页版官方入口 126邮箱账号在线登录平台  MAC如何将整个网页截长图_MAC使用Safari的导出为PDF或第三方工具  React/Next.js中实现列表项的动态移动与状态管理:兼论唯一键的重要性  CSS Grid如何控制元素对齐_align-items与justify-items组合使用  J*aScript:在map操作中高效处理空数组  在Typer应用中优雅地处理和重组任意命令行参数  Gmail邮箱申请注册直达_Gmail邮箱免费注册PC版官网入口2025  AO3官网镜像链接 Archive of Our Own同人文在线浏览  c++如何使用Meson构建系统_c++比CMake更快的构建工具  支付宝如何管理隐私设置_支付宝隐私保护的配置技巧  俄罗斯Yandex搜索引擎入口_Yandex官网免登录一键访问  c++ 获取系统当前时间 c++时间戳获取方法  composer 和 npm/yarn 在管理依赖方面有什么核心思想差异?  Lar*el 递归关系中排除指定分支的教程  Win10系统怎么查看已安装更新_Win10卸载有问题的更新补丁  win11怎么查看应用耗电情况 Win11电池设置查看应用能耗排行榜【优化】  Node.js中HTML按钮与J*aScript函数交互的正确姿势  谷歌浏览器如何快速清除某个网站的数据_Chrome网站缓存清理方法  163邮箱官方主页登录 直达网易邮箱登录核心页面  AO3访问入口汇总 AO3网页版同人作品一键直达  《马克思佩恩3》早期版本曝光 UI设计曾多次调整!  JUnit5/Mockito:优雅测试内部依赖与异常处理的实践  京东京造J1和网易云音乐氧气真无线有什么不同_国产电商蓝牙耳机音质对比 

搜索