React Server Components手把手教学(三)

本文涉及的产品
云数据库 MongoDB,独享型 2核8GB
推荐场景:
构建全方位客户视图
简介: React Server Components手把手教学(三)

服务器组件与客户端代码完全兼容

服务器组件与客户端代码完全兼容,这意味着客户端组件和服务器组件可以在同一个 React 树中进行渲染。通过将大部分应用程序代码移到服务器上,服务器组件有助于防止客户端数据获取的瀑布效应,快速解决服务器端的数据依赖关系。

在传统的客户端渲染中,组件使用 React Suspense“暂停”其渲染过程(并显示回退状态),同时等待异步工作完成。通过服务器组件,数据获取和渲染都在服务器上进行,因此 Suspense 也会在服务器端管理等待期,从而缩短总的往返时间,加快回退和完成页面的渲染。

需要注意的是,客户端组件在初始加载时仍然进行服务器端渲染(SSR)。服务器组件模型并不取代 SSR 或 Suspense,而是与它们一起工作,根据需要为用户提供应用程序的所有部分

image.png

在使用 Next.jsReact 服务器组件时,数据获取和 UI 渲染可以在同一个组件中完成。此外,服务器操作(Server Actions)为用户提供了在页面上的 JavaScript 加载之前与服务器端数据进行交互的方式。


9. 如何使用Next.js和MongoDB构建课程列表页面

现在让我们用Next.js构建一个使用RSC的应用程序。

因此,我们现在将构建一个课程列表页面,以展示我们如何在Next.js中创建服务器组件,以及它与客户端组件的不同之处。

请注意,我们不会在这里深入学习Next.jsMongoDB。我们只是将这个应用程序作为一个示例,来教我们RSC的工作原理以及它们与客户端组件的区别。

首先,让我们将课程数据添加到数据存储中。对于这个应用程序,我使用了MongoDB。下面的图像显示添加了三个课程的三个文档。

image.png

接下来,我们将创建一个实用函数来建立与MongoDB的连接。这是一个通用的代码,我们可以在任何基于JavaScript的项目中使用它,以使用MongooseMongoDB URI连接到MongoDB

import mongoose from "mongoose";
export async function dbConnect(): Promise<any> {
  try {
    const conn = await mongoose.connect(String(process.env.MONGO_DB_URI));
    console.log(`Database connected : ${conn.connection.host}`);
    return conn;
  } catch (err) {
    console.error(err);
  }
}

现在,我们需要创建与MongoDB文档相对应的模型(modal)。由于我们处理的是课程数据,这是与之对应的模型:

import mongoose, { Schema } from "mongoose";
const schema = new Schema({
  name: {
      required: true,
      type: String
  },
  description: {
      required: true,
      type: String
  },
  cover: {
    required: true,
    type: String
  },
  rating: {
    required: true,
    type: Number
  },
  price: {
    required: true,
    type: Number
  },
  createdOn: {
    type: { type: Date, default: Date.now }
  },
  link: {
    required: true,
    type: String
  },
  type: {
    required: true,
    type: String
  },
  comments: {
    required: false,
    type: [{ body: String, date: Date }]
  }
});
export const courses = mongoose.models.course ?? mongoose.model("course", schema);

通过Next.js App Router,所有的组件默认都是服务器组件。这意味着它们位于靠近服务器的位置,并且可以访问我们的服务器生态系统。

下面的代码是一个常规的Next.js组件,但具有一个特殊功能:我们可以在组件中直接获取数据库连接,并直接查询数据,而无需经过任何状态和效果管理

从该组件中记录的任何内容都不会被记录到我们的浏览器控制台,因为这是一个服务器组件。我们可以在服务器控制台中查看日志(我们可以使用yarn dev命令启动服务器的终端)。

由于与数据库的交互是异步的,我们在进行调用时使用await关键字,并在组件上使用async关键字。在接收到响应后,我们将其作为属性传递给子组件。

import { dbConnect } from '@/services/mongo'
import { courses } from '@/models/courseModel'
import { addCourseToDB } from './actions/add-course'
import AddCourse from './components/AddCourse'
import CourseList from './components/CourseList'
export default async function Home() {
  // 建立MongoDB链接
  await dbConnect();
  //获取所有的数据信息
  const allCourses = await courses.find().select(
              ["name", "cover", "rating"]);
  // 在服务器终端中打印显示数据
  console.log({allCourses})
  return (
    <main>
      <div>
        <h1>Courses</h1> 
        <AddCourse addCourseToDB={addCourseToDB} />
        <CourseList allCourses={allCourses} />  
      </div>
    </main>
  )
}

Home组件包含:

  • 一个标题
  • 一个组件(AddCourse),用于包装一个添加课程的按钮
  • 一个组件(CourseList),用于将课程显示为列表。

image.png

我们知道,服务器组件可以同时渲染客户端和服务器组件AddCourse组件需要用户交互,即用户需要点击按钮来添加课程。所以它不能是服务器组件.

因此,让我们为AddCourse创建一个客户端组件。通过Next.js App Router,默认情况下,所有组件都是服务器组件。

如果我们想创建一个客户端组件,我们必须在组件顶部(甚至在任何导入语句之前)使用名为use client的指令来明确创建一个客户端组件。

客户端组件- AddCourse

'use client'
import { useState } from 'react';
import Modal from './Modal';
import AddCourseForm from "./AddCourseForm";
export default function AddCourse({
  addCourseToDB,
}: {
  addCourseToDB: (data: any) => Promise<void>
}) {
  const [showAddModal, setShowAddModal] = useState(false);
  const add = async(data: any) => {
    await addCourseToDB(data);
    setShowAddModal(false);
  }
  return (
    <>
      <button
        onClick={() => setShowAddModal(true)}
      >
        Add Course
      </button>
      <Modal 
        shouldShow={showAddModal} 
        body={
          <AddCourseForm 
            saveAction={add} 
            cancelAction={() => setShowAddModal(false)} />} />
    </>
  )
}

服务器组件 -CourseList

CourseList组件不需要任何事件处理程序,因此我们可以将其保持为服务器组件。

import Image from 'next/image'
import Link from 'next/link'
export default function CourseList(courseList: any) {
  const allCourses = courseList.allCourses;
  return(
    <div>
      {
        allCourses.map((course: any) =>
        <Link key={course['_id']} href={`/courses/${course['_id']}`}>
          <div>
            <Image
              src={course.cover}
              width={200}
              height={200}
              alt={course.name}
            />
            <h2>{course.name}</h2>
            <p>{course.rating}</p>
          </div> 
        </Link> 
      )}
    </div>  
  )
}
我们打开浏览器开发工具的Sources选项卡,以确定客户端上下载了什么,服务器上留下了什么。我们在这里是看不到page.tsx文件或CourseList.tsx文件信息。这是因为这些是服务器组件,它们永远不会成为我们的客户端捆绑包的一部分

我们只会看到我们在应用程序中明确标记为客户端组件的组件。

image.png

Next.js App Router 中,所有获取的数据现在默认为静态数据,在构建时渲染。然而,这可以很容易地改变:Next.js 扩展了 fetch 选项对象,以提供缓存和重新验证规则的灵活性。

我们可以使用 {next: {revalidate: number}} 选项以设置的时间间隔或在后端更改发生时刷新静态数据(增量静态再生成),而 {cache: 'no-store'} 选项可以在动态数据的 fetch 请求中传递(服务器端渲染)。


总结

总结一下:

  • React服务器组件具有后端访问权限,无需进行任何网络往返。
  • 我们可以通过使用RSC来避免网络瀑布问题。
  • React服务器组件支持自动代码拆分,并通过零捆绑大小提高应用程序的性能。
  • 由于这些组件位于服务器端,它们无法访问客户端端的事件处理程序、状态和效果。这意味着我们不能使用任何事件处理程序或React钩子,如useStateuseReduceruseEffect
  • React服务器组件可以导入并渲染客户端组件,但反之则不成立。但我们可以将服务器组件作为props传递给客户端组件。
  • RSC并不意味着取代客户端组件。健康的应用程序同时使用服务器组件来进行动态数据获取以及客户端组件来实现丰富的交互性。挑战在于确定何时使用每种组件。

后记

分享是一种态度

参考资料:

  1. understanding-react-server-components
  2. react-server-components-for-beginners/
  3. how-to-use-react-server-components/
  4. what-even-are-react-server-components/

全文完,既然看到这里了,如果觉得不错,随手点个赞和“在看”吧。

相关实践学习
MongoDB数据库入门
MongoDB数据库入门实验。
快速掌握 MongoDB 数据库
本课程主要讲解MongoDB数据库的基本知识,包括MongoDB数据库的安装、配置、服务的启动、数据的CRUD操作函数使用、MongoDB索引的使用(唯一索引、地理索引、过期索引、全文索引等)、MapReduce操作实现、用户管理、Java对MongoDB的操作支持(基于2.x驱动与3.x驱动的完全讲解)。 通过学习此课程,读者将具备MongoDB数据库的开发能力,并且能够使用MongoDB进行项目开发。 &nbsp; 相关的阿里云产品:云数据库 MongoDB版 云数据库MongoDB版支持ReplicaSet和Sharding两种部署架构,具备安全审计,时间点备份等多项企业能力。在互联网、物联网、游戏、金融等领域被广泛采用。 云数据库MongoDB版(ApsaraDB for MongoDB)完全兼容MongoDB协议,基于飞天分布式系统和高可靠存储引擎,提供多节点高可用架构、弹性扩容、容灾、备份回滚、性能优化等解决方案。 产品详情: https://www.aliyun.com/product/mongodb
相关文章
|
2月前
|
前端开发 JavaScript 测试技术
React Server Side Rendering (SSR) 详解
【10月更文挑战第19天】React Server Side Rendering (SSR) 是一种在服务器端渲染 React 应用的技术,通过在服务器上预先生成 HTML 内容,提高首屏加载速度和 SEO。本文从概念入手,逐步探讨 SSR 的实现步骤、常见问题及解决方案,并通过代码示例进行说明。
405 3
|
5月前
|
前端开发 JavaScript 算法
React Server Component 使用问题之想在路由切换时保持客户端状态,如何实现
React Server Component 使用问题之想在路由切换时保持客户端状态,如何实现
|
5月前
|
前端开发 JavaScript PHP
React Server Component 使用问题之路由的能力,如何实现
React Server Component 使用问题之路由的能力,如何实现
|
5月前
|
前端开发 JavaScript
React Server Component 使用问题之添加jsx的组件化能力,如何操作
React Server Component 使用问题之添加jsx的组件化能力,如何操作
|
5月前
|
前端开发 PHP 开发者
React Server Component 使用问题之怎么使用Docker运行PHP应用
React Server Component 使用问题之怎么使用Docker运行PHP应用
|
5月前
|
开发者
🔥揭秘JSF导航:如何轻松驾驭页面跳转与流程控制?🎯
【8月更文挑战第31天】在 JavaServer Faces(JSF)中,导航规则是控制页面跳转和流程的关键。本文详细介绍 JSF 的导航规则,包括转发和重定向等跳转方式,并通过 `faces-config.xml` 文件配置示例展示如何实现不同场景下的页面跳转及流程控制,帮助开发者有效管理应用程序的页面流和用户交互,提升应用质量。
68 0
|
5月前
|
前端开发 搜索推荐 UED
React Server Side Rendering的神奇之处:如何用SSR提升SEO与首屏加载速度,让你的项目一鸣惊人?
【8月更文挑战第31天】在现代Web开发中,React服务器端渲染(SSR)能显著提升SEO性能和首屏加载速度。通过在服务器端预渲染组件并发送HTML至客户端,SSR不仅优化了首屏加载时间,增强了用户体验,还生成了便于搜索引擎抓取的静态HTML文件,提升了页面排名。此外,SSR还具备提高安全性的优点,能够有效防范XSS攻击。虽然其开发复杂性和服务器负载是潜在劣势,但借助如Next.js等库、编写高效组件及定期维护等最佳实践,可以充分发挥SSR的优势,为未来Web开发注入更强动力。
78 0
|
5月前
|
前端开发 JavaScript 开发者
React Server Component 使用问题之为什么选择使用 React 官方的 renderToString 来渲染 HTML,如何解决
React Server Component 使用问题之为什么选择使用 React 官方的 renderToString 来渲染 HTML,如何解决
|
7月前
|
前端开发 JavaScript 算法
RSC 就是套壳 PHP ?带你从零实现 React Server Component
RSC 就是套壳 PHP ?带你从零实现 React Server Component
|
Rust 前端开发 JavaScript
用Rust搭建React Server Components 的Web服务器(三)
用Rust搭建React Server Components 的Web服务器(三)
137 0