Next.js 13.4.10中如何在同页面实现SSR与投票类客户端交互
在Next.js 13.4.10中同时实现SSR内容交付与客户端投票交互
完全可以实现,Next.js 13+的App Router支持服务器组件与客户端组件混合使用,刚好能满足你的需求:服务器组件负责SSR渲染帖子内容(保证搜索引擎可见),客户端组件封装投票交互逻辑(仅在客户端执行)。
具体实现步骤:
1. 拆分投票交互为客户端组件
创建独立的VoteButton.tsx组件,添加'use client'指令标记为客户端组件,在内部处理投票逻辑与本地状态更新:
'use client'; import { useState } from 'react'; interface VoteButtonProps { postId: number; initialVote: number; } export default function VoteButton({ postId, initialVote }: VoteButtonProps) { const [voteCount, setVoteCount] = useState(initialVote); const handleVote = async (direction: number) => { // 调用后端API更新票数 await fetch(`/api/vote/${postId}`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ vote: direction }), }); // 本地即时更新票数,提升用户体验 setVoteCount(prev => prev + direction); }; return ( <div> <p>vote: {voteCount}</p> <button onClick={() => handleVote(1)}> + </button>{' '} <button onClick={() => handleVote(-1)}> - </button> </div> ); }
2. 保留主页为服务器组件
原Home组件作为服务器组件(无需'use client'),负责在服务器端获取数据、渲染帖子内容,并引入客户端投票组件:
interface Post { id: number; title: string; body: string; vote: number; } async function getPosts(): Promise<Post[]> { const res = await fetch('https://jsonplaceholder.typicode.com/posts', { next: { revalidate: 60 }, // 可选:设置60秒自动重新验证,实现增量静态再生 }); // 注意:jsonplaceholder返回的帖子无vote字段,手动添加默认值 const posts = await res.json(); return posts.map(post => ({ ...post, vote: 0 })); } import VoteButton from './VoteButton'; export default async function Home() { const posts = await getPosts(); return ( <> {posts.map((post: Post) => ( <div key={post.id}> <h2>{post.title}</h2> <p>{post.body}</p> <VoteButton postId={post.id} initialVote={post.vote} /> </div> ))} </> ); }
3. 创建API路由处理投票请求
在app/api/vote/[postId]/route.ts中编写后端逻辑,处理票数更新:
import { NextResponse } from 'next/server'; export async function POST( request: Request, { params }: { params: { postId: string } } ) { const { vote } = await request.json(); const postId = params.postId; // 替换为你的实际业务逻辑:比如操作数据库更新对应帖子的票数 console.log(`Post ${postId} 票数更新:${vote > 0 ? '+' : ''}${vote}`); return NextResponse.json({ success: true }); }
核心原理:
- 服务器组件(Home):在服务器端完成数据获取与HTML渲染,生成的静态内容能被搜索引擎正常抓取,完全符合SSR需求。
- 客户端组件(VoteButton):仅在客户端加载并执行JS,处理点击事件与状态更新,不会影响服务器端渲染的内容。两者通过props传递初始数据,实现无缝结合。
内容的提问来源于stack exchange,提问作者Nori
相关产品推荐
相关产品推荐

