React 19 与服务端组件

React 19 与服务端组件

React 19 彻底改变了组件的渲染方式。

服务端组件

基本概念

// 服务端组件 - 默认
async function UserProfile({ userId }) {
  // 直接访问数据库
  const user = await db.users.find(userId)
  
  return (
    <div>
      <h1>{user.name}</h1>
      <p>{user.email}</p>
    </div>
  )
}

// 客户端组件 - 需要标记
'use client'

function InteractiveButton({ onClick }) {
  const [count, setCount] = useState(0)
  
  return (
    <button onClick={() => setCount(c => c + 1)}>
      Clicked {count} times
    </button>
  )
}

混合渲染

// 服务端组件可以包含客户端组件
async function Page() {
  const posts = await fetchPosts() // 服务端
  
  return (
    <div>
      <h1>Blog</h1>
      <PostList posts={posts} />
      <LikeButton /> {/* 客户端 */}
    </div>
  )
}

流式渲染

import { Suspense } from 'react'

function BlogPage() {
  return (
    <div>
      <h1>My Blog</h1>
      <Suspense fallback={<Skeleton />}>
        <SlowComponent />
      </Suspense>
    </div>
  )
}

// 服务端流式传输
async function SlowComponent() {
  const data = await slowFetch()
  return <Content data={data} />
}

自动优化

代码分割

// React 19 自动分割
const HeavyComponent = lazy(() => import('./Heavy'))

function Page() {
  return (
    <Suspense fallback={<Loading />}>
      <HeavyComponent />
    </Suspense>
  )
}

预加载

// 预加载组件和数据
function PostLink({ slug }) {
  // 鼠标悬停时预加载
  const prefetch = usePrefetch()
  
  return (
    <a 
      href={`/posts/${slug}`}
      onMouseEnter={() => prefetch(`/api/posts/${slug}`)}
    >
      Read more
    </a>
  )
}

新 Hooks

use

// 统一的数据获取方式
function UserCard({ id }) {
  const user = use(fetchUser(id))
  return <div>{user.name}</div>
}

// 配合 Suspense
function Page() {
  return (
    <Suspense fallback={<Loading />}>
      <UserCard id="123" />
    </Suspense>
  )
}

useOptimistic

function LikeButton({ postId, initialLikes }) {
  const [likes, setOptimisticLikes] = useOptimistic(
    initialLikes,
    (state, newLike) => state + (newLike ? 1 : -1)
  )
  
  async function handleLike() {
    setOptimisticLikes(true) // 乐观更新
    await likePost(postId)   // 服务端确认
  }
  
  return <button onClick={handleLike}>{likes} likes</button>
}

性能对比

指标React 18React 19首屏时间2.5s0.8sJS 体积150KB45KB交互时间3.2s1.2s

最佳实践

  1. 优先使用服务端组件

  2. 客户端组件仅用于交互

  3. 合理使用 Suspense

  4. 流式渲染提升体验

  5. 预加载关键资源

ReactNext.js
返回首页