Skip to main content

客户端渲染 (CSR)

在使用 React 的客户端渲染 (CSR) 中,浏览器会下载最小的 HTML 页面以及该页面所需的 JavaScript。然后 JavaScript 用于更新 DOM 并渲染页面。首次加载应用时,用户可能会注意到在看到完整页面之前有轻微的延迟,这是因为直到下载、解析和执行所有 JavaScript 后页面才完全渲染。

¥In Client-Side Rendering (CSR) with React, the browser downloads a minimal HTML page and the JavaScript needed for the page. The JavaScript is then used to update the DOM and render the page. When the application is first loaded, the user may notice a slight delay before they can see the full page, this is because the page isn't fully rendered until all the JavaScript is downloaded, parsed, and executed.

首次加载页面后,导航到同一网站上的其他页面通常会更快,因为只需要获取必要的数据,并且 JavaScript 可以重新渲染页面的部分内容,而无需刷新整个页面。

¥After the page has been loaded for the first time, navigating to other pages on the same website is typically faster, as only necessary data needs to be fetched, and JavaScript can re-render parts of the page without requiring a full page refresh.

在 Next.js 中,有两种方法可以实现客户端渲染:

¥In Next.js, there are two ways you can implement client-side rendering:

  1. 在页面中使用 React 的 useEffect() 钩子,而不是服务器端渲染方法(getStaticPropsgetServerSideProps)。

    ¥Using React's useEffect() hook inside your pages instead of the server-side rendering methods (getStaticProps and getServerSideProps).

  2. 使用 SWRTanStack 查询 之类的数据获取库在客户端获取数据(推荐)。

    ¥Using a data fetching library like SWR or TanStack Query to fetch data on the client (recommended).

以下是在 Next.js 页面中使用 useEffect() 的示例:

¥Here's an example of using useEffect() inside a Next.js page:

import React, { useState, useEffect } from 'react'

export function Page() {
const [data, setData] = useState(null)

useEffect(() => {
const fetchData = async () => {
const response = await fetch('https://api.example.com/data')
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`)
}
const result = await response.json()
setData(result)
}

fetchData().catch((e) => {
// handle the error as needed
console.error('An error occurred while fetching the data: ', e)
})
}, [])

return <p>{data ? `Your data: ${data}` : 'Loading...'}</p>
}

在上面的示例中,组件从渲染 Loading... 开始。然后,一旦获取数据,它就会重新渲染并显示数据。

¥In the example above, the component starts by rendering Loading.... Then, once the data is fetched, it re-renders and displays the data.

尽管在 useEffect 中获取数据是你可能在旧版 React 应用中看到的一种模式,但我们建议使用数据获取库以获得更好的性能、缓存、乐观更新等。这是使用 SWR 在客户端获取数据的最小示例:

¥Although fetching data in a useEffect is a pattern you may see in older React Applications, we recommend using a data-fetching library for better performance, caching, optimistic updates, and more. Here's a minimum example using SWR to fetch data on the client:

import useSWR from 'swr'

export function Page() {
const { data, error, isLoading } = useSWR(
'https://api.example.com/data',
fetcher
)

if (error) return <p>Failed to load.</p>
if (isLoading) return <p>Loading...</p>

return <p>Your Data: {data}</p>
}

很高兴知道:

¥Good to know:

请记住,企业社会责任会影响搜索引擎优化。某些搜索引擎爬虫可能不会执行 JavaScript,因此只能看到应用的初始空或加载状态。对于互联网连接或设备较慢的用户来说,它还可能导致性能问题,因为他们需要等待所有 JavaScript 加载并运行才能看到完整页面。Next.js 提倡一种混合方法,允许你根据应用中每个页面的需求结合使用 服务器端渲染静态站点生成 和客户端渲染。在 App Router 中,你还可以使用 加载带有 Suspense 的 UI 在渲染页面时显示加载指示器。

¥Keep in mind that CSR can impact SEO. Some search engine crawlers might not execute JavaScript and therefore only see the initial empty or loading state of your application. It can also lead to performance issues for users with slower internet connections or devices, as they need to wait for all the JavaScript to load and run before they can see the full page. Next.js promotes a hybrid approach that allows you to use a combination of server-side rendering, static site generation, and client-side rendering, depending on the needs of each page in your application. In the App Router, you can also use Loading UI with Suspense to show a loading indicator while the page is being rendered.