Next.js加载异步组件 骨架屏

Next.js 中有两种处理页面加载的方式,一种是 Loading UI 一种是 Streaming。接下来我将介绍这两种的区别,以及实际的业务场景。

当我们进入某个页面时,需要获取页面数据,可能是从数据库读取也有可能是 API 服务,总之这是一个异步任务,我们可以在获取数据过程中提示用户数据正在加载,比如放置一些骨架屏,提升用户的体验。

如果不对这些进行处理,使用体验会大打折扣。

假设我们有一个场景,进入 /posts 页面后获取所有的文章数据。

app/posts/page.tsx

import Link from "next/link";

const PostsPage = async () => {
  const posts = await fetch("https://jsonplaceholder.typicode.com/posts").then(
    (response) => response.json()
  );

	// await new Promise((resolve) => setTimeout(resolve, 2000));

  return (
    <div className="p-10 max-w-3xl mx-auto">
      <ul className="list-decimal">
        {posts.map((post) => (
          <li key={post.id} className="">
            <h2 className="text-xl font-semibold my-2">
              <Link href={`/posts/${post.id}`} className="hover:underline">
                {post.title}
              </Link>
            </h2>
            <p>{post.body}</p>
          </li>
        ))}
      </ul>
    </div>
  );
};

export default PostsPage;

可以解开上面的注释延长加载时间。

如果我们从首页进入到 /posts 页面,不会立即进入,需要等待 await 之后才会进入页面,这个等待时间就取决于我们的网络了,当网络较差时,可能很久才获取数据,这就大大影响了用户体验。

Loading UI

在 posts 同级目录创建 app/posts/loading.tsx 文件:
(ps:我项目使用的 TypeScript,如果是 JavaScript 则为 jsx 后缀)

const PostsLoading = () => {
  return <p>Loading...</p>;
};

export default PostsLoading;

这样当我们进入 /posts 页面后不会等待数据加载完成后才进入页面,而是直接进入 /posts 页面,数据加载过程中显示的内容为 loading.tsx 文件的内容,我们就可以写一些文字提示或者骨架屏之类的内容。

Streaming (Suspense)

另一种方式,也是比较推荐的方式:Streaming (Suspense),流式传输。

比如我们一个页面有多个异步组件,有文章、评论等等,如果我们使用上述第一种方案,页面会等所有的数据加载完成才渲染,而通过 Suspense 可以对每一个组件异步渲染。

image.png

React 18 引入了 Suspense 组件,支持在组件树中展示异步组件。Next.js 利用这一特性,让开发者可以定义一个组件在加载期间显示的备选内容。

通过 Suspense,你可以在组件等待数据时显示一个备用 UI,这样用户就不会看到不完整的空白界面。一旦数据加载完毕,React 将渲染实际的组件。这种异步加载方式特别适用于大型组件或数据,它们可能需要长时间来加载和渲染。

新建 app/posts2/page.tsx 文件:

import Link from "next/link";
import { Suspense } from "react";

const Posts2Page = () => {
  return (
    <div>
      <Suspense fallback={<PostsSkeleton />}>
        <PostList />
      </Suspense>
    </div>
  );
};

const PostsSkeleton = () => {
  return (
    <div className="p-10 max-w-3xl mx-auto">
      <ul className="space-y-2 list-decimal">
        {[...Array(5).keys()].map((i) => (
          <li key={i} className="space-y-2">
            <div
              className="animate-pulse h-7 w-1/2 bg-slate-200 rounded duration-1000"
              style={{
                animationDelay: `${i * 0.05}s`,
              }}
            ></div>
            <div
              className="animate-pulse h-5 w-full bg-slate-200 rounded duration-1000"
              style={{
                animationDelay: `${i * 0.05}s`,
              }}
            ></div>
            <div
              className="animate-pulse h-5 w-3/4 bg-slate-200 rounded duration-1000"
              style={{
                animationDelay: `${i * 0.05}s`,
              }}
            ></div>
          </li>
        ))}
      </ul>
    </div>
  );
};

const PostList = async () => {
  const posts = await fetch("https://jsonplaceholder.typicode.com/posts").then(
    (response) => response.json()
  );

  await new Promise((resolve) => setTimeout(resolve, 1000));

  return (
    <div className="p-10 max-w-3xl mx-auto">
      <ul className="list-decimal">
        {posts.map((post) => (
          <li key={post.id} className="">
            <h2 className="text-xl font-semibold my-2">
              <Link href={`/posts/${post.id}`} className="hover:underline">
                {post.title}
              </Link>
            </h2>
            <p>{post.body}</p>
          </li>
        ))}
      </ul>
    </div>
  );
};

export default Posts2Page;

Posts2Page 使用 Suspense 组件包裹 PostList 组件。当 PostList 组件在加载数据时,Suspense 会显示它的 fallback 属性,也就是 PostsSkeleton 组件。

PostsSkeleton 是一个骨架屏组件,用于在数据加载时显示。它会显示5个文章的占位符。

PostList 是一个异步组件,从 https://jsonplaceholder.typicode.com/posts 这个 URL 获取文章数据,然后显示出来。

2023-12-13_15-38-10.gif

最后,如果文章对您有所帮助,还希望能够点赞、收藏、关注,您的每一次点击都会为我带来无穷的动力来写出更好的文章。

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

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

相关文章

Linux---进程概念

目录 一、冯诺依曼体系结构 二、操作系统 1.关于下三层的理解 2.关于上三层的理解 三、进程 1.进程(也叫做任务)对应的标识符---pid 2.fork---用代码创建进程(系统接口) 1&#xff09;初步认识一下fork 2&#xff09;fork函数的返回值 3&#xff09;fork的原理 问题1…

残差网络中的BN (Batch Normalization 批标准化层)的作用是什么?

文章目录 什么是BN &#xff08;Batch Normalization 批标准化层&#xff09;一、BN层对输入信号进行以下操作:二、BN 层有什么作用&#xff1f; 什么是BN &#xff08;Batch Normalization 批标准化层&#xff09; BN层的全称是Batch Normalization层,中文可以翻译为批标准化…

[Big Bird]论文解读:Big Bird: Transformers for Longer Sequences

文章目录 1 介绍2 模型架构3 结果 论文&#xff1a;Big Bird: Transformers for Longer Sequences 作者&#xff1a;Manzil Zaheer, Guru Guruganesh, Avinava Dubey, Joshua Ainslie, Chris Alberti, Santiago Ontanon, Philip Pham, Anirudh Ravula, Qifan Wang, Li Yang, Am…

多维时序 | MATLAB实现RIME-LSSVM【23年新算法】基于霜冰优化算法(RIME)优化最小二乘向量机(LSSVM)多变量时间序列预测

多维时序 | MATLAB实现RIME-LSSVM【23年新算法】基于霜冰优化算法(RIME)优化最小二乘向量机(LSSVM)多变量时间序列预测 目录 多维时序 | MATLAB实现RIME-LSSVM【23年新算法】基于霜冰优化算法(RIME)优化最小二乘向量机(LSSVM)多变量时间序列预测预测效果基本介绍模型描述程序设…

【最新版】在WSL上运行 Linux GUI (图形用户界面)应用(Gnome 文本编辑器、GIMP、Nautilus、VLC、X11 应用)

文章目录 一、 安装WSL1. 全新安装2. 现有 WSL 安装 二、运行 Linux GUI 应用1. 更新发行版中的包2. 安装 Gnome 文本编辑器启动 3. 安装 GIMP启动 4. 安装 Nautilus启动 5. 安装 VLC启动 6. 安装 X11 应用 适用于 Linux 的 Windows 子系统 (WSL) 现在支持在 Windows 上运行 Li…

深入比较Input、Change和Blur事件:Vue与React中的行为差异解析

目录 前言 1. Input事件&#xff1a; 行为差异&#xff1a; 2. Change事件&#xff1a; 行为差异&#xff1a; 3. Blur事件&#xff1a; 行为差异&#xff1a; 4. 在Vue中的表现&#xff1a; Input事件&#xff1a; Change事件&#xff1a; Blur事件&#xff1a; 5.…

Quartus 18.1软件及支持包安装教程

安装前最好关闭电脑的杀毒软件和防火墙 安装包可以到Quartus官网下载需要的版本&#xff0c;注意选择操作系统 Quartus官网&#xff1a;FPGA 设计软件 - 英特尔 Quartus Prime (intel.cn) 下载解压后以管理员的身份运行 QuartusSetup-18.1.0.625.exe文件&#xff0c;版本不同…

Vue中的数据变化监控与响应——深入理解Watchers

目录 ​编辑 前言 1. 基本用法&#xff1a; 2. 深度监听&#xff1a; 3. 立即执行&#xff1a; 4. 监听多个数据&#xff1a; 5. 清理监听器&#xff1a; 6. 监听路由变化&#xff1a; 总结&#xff1a; 我的其他博客 前言 在Vue.js中&#xff0c;watch是一种用于监听…

【Spring】Spring中的事务

文章目录 1. Spring事务简介2. Spring事务的案例案例代码代码目录结构数据库pom.xmlResource/jdbc.propertiesconfig/SpringConfig.javaconfig/JdbcConfig.javaconfig/MyBatisConfig.javadao/AccountDao.javaservice/AccountService.javaservice/impl/AccountServiceImpl.java测…

设计模式 简单工厂 工厂方法模式 抽象工厂模式

工厂模式介绍 工厂模式是我们最常用的实例化对象模式了&#xff0c;是用工厂方法代替new操作的一种模式。它是创建型模式。 简单工厂 简单工厂模式是指由一个工厂对象决定创建出哪一种产品类的实例, 但它不属于GOF 23种设计模式 简单工厂适用于工厂类负责创建的对象较少的场景,…

Command line is too long. Shorten command line for Application or also

一、问题描述 Error running ‘Application’: Command line is too long. Shorten command line for Application or also for Spring Boot default configuration? 二、原因分析 springboot项目启动命令过长&#xff01; 三、解决方案 第1步:点击项目启动配置项 第2步…

基于ssm的简单学校课程管理系统的设计与实现(源码+调试)

项目描述 临近学期结束&#xff0c;还是毕业设计&#xff0c;你还在做java程序网络编程&#xff0c;期末作业&#xff0c;老师的作业要求觉得大了吗?不知道毕业设计该怎么办?网页功能的数量是否太多?没有合适的类型或系统?等等。今天给大家介绍一篇基于ssm的简单学校课程管…

vue2项目vue-qrcode-reader 扫一扫二维码插件

vue2项目 vue-qrcode-reader 扫一扫二维码插件 问题所在解决办法成功展示 问题所在 今天在引导师弟做扫二维码功能&#xff0c;发现通过npm install --save vue-qrcode-reade安装死活就是报错TypeError: Object...) is not a function 解决办法 百度了很多大牛的博客&#…

国内访问GitHub很卡,steam连接断开怎么办

目录 第一章、问题分析1.1&#xff09;问题1.2&#xff09;解决&#xff1a;下载个加速器就好了 友情提醒: 先看文章目录&#xff0c;大致了解文章知识点结构&#xff0c;点击文章目录可直接跳转到文章指定位置。 第一章、问题分析 1.1&#xff09;问题 国内访问GitHub很卡怎…

数据分析(一)(附带实例和源码)

一、主要目的&#xff1a; 主要利用Python包&#xff0c;如Numpy、Pandas和Scipy等常用分析工具并结合常用的统计量来进行数据的描述&#xff0c;把数据的特征和内在结构展现出来。熟悉在Python开发环境中支持数据分析的可用模块以及其中的方法&#xff0c;基于一定的样例数据…

Windows中安装Git软件和TortoiseGit软件

1、git软件下载地址 https://git-scm.com/download/win 2、TortoiseGit软件下载 >https://tortoisegit.org/download/ 3、软件安装 4、环境安装说明 上面介绍的是在Windows中使用git&#xff0c;如果你电脑已经装了Ubuntu系统&#xff0c;可以直接在Ubuntu中使用git命令提…

arthas获取spring bean

参考文章 arthas获取spring bean 写一个工具Util package com.example.lredisson.util;import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import o…

[RK-Linux] 移植Linux-5.10到RK3399(七)| 检查GPIO与LED节点,使能风扇接口

文章目录 一、原理图二、设备树配置三、节点控制一、原理图 ROC-RK3399-PC Pro 的 LED 接口如图: 工作灯 WORK_LED (蓝色灯)网络连接到 GPIO2_D3: DIY_LED (红色灯)网络连接到 GPIO0_B5: ROC-RK3399-PC Pro 要控制的 GPIO 接口主要是风扇,如图: FAN_CTL 网络连接到

【Java】SpringBoot中实现Redis Stream队列

SpringBoot实现Redis Stream队列 前言 简单实现一下在SpringBoot中操作Redis Stream队列的方式&#xff0c;监听队列中的消息进行消费。 jdk&#xff1a;1.8 springboot-version&#xff1a;2.6.3 redis&#xff1a;5.0.1&#xff08;5版本以上才有Stream队列&#xff09;…

【C++】STL 容器 - string 字符串操作 ⑤ ( string 字符串查找 | find 函数查找字符串 | rfind 函数查找字符串 )

文章目录 一、string 字符查找 - find 函数查找字符串1、string 类 find 函数原型说明2、代码示例 - 字符串查找3、代码示例 - 统计字符串子串 二、string 字符查找 - rfind 函数查找字符串1、string 类 rfind 函数原型说明2、代码示例 - rfind 字符串查找 一、string 字符查找…