fix: use Link + router.refresh() for optimal navigation

Based on Next.js best practices research:
- Use <Link> component for prefetching and client-side navigation
- Add router.refresh() onClick to force server component re-render
- This preserves SPA experience while ensuring fresh data
- Fixes issue where pages don't reload after URL change
This commit is contained in:
Your Name 2026-01-26 21:38:06 +08:00
parent 8e82b0ea99
commit 9aa1453f80
2 changed files with 34 additions and 45 deletions

View File

@ -1,4 +1,7 @@
"use client";
import Link from "next/link";
import { useRouter } from "next/navigation";
import { memo } from "react";
import { useChatVisibility } from "@/hooks/use-chat-visibility";
import type { Chat } from "@/lib/db/schema";
@ -37,6 +40,7 @@ const PureChatItem = ({
onDelete: (chatId: string) => void;
setOpenMobile: (open: boolean) => void;
}) => {
const router = useRouter();
const { visibilityType, setVisibilityType } = useChatVisibility({
chatId: chat.id,
initialVisibilityType: chat.visibility,
@ -45,7 +49,13 @@ const PureChatItem = ({
return (
<SidebarMenuItem>
<SidebarMenuButton asChild isActive={isActive}>
<Link href={`/chat/${chat.id}`} onClick={() => setOpenMobile(false)}>
<Link
href={`/chat/${chat.id}`}
onClick={() => {
setOpenMobile(false);
router.refresh();
}}
>
<span>{chat.title}</span>
</Link>
</SidebarMenuButton>

View File

@ -174,21 +174,15 @@ export function TopNavbar({
)}
{/* AI智能精选 */}
<Button
variant="ghost"
size="sm"
className="flex items-center gap-1 h-8 px-3 text-white hover:bg-white/15 hover:text-white rounded-full transition-colors"
onClick={(e) => {
e.preventDefault();
e.stopPropagation();
router.push("/featured");
}}
type="button"
<Link
href="/featured"
className="flex items-center gap-1 h-8 px-3 text-white hover:bg-white/15 hover:text-white rounded-full transition-colors text-sm font-medium"
title="AI智能精选"
onClick={() => router.refresh()}
>
<Sparkles className="h-4 w-4 text-yellow-400" />
<span className="text-sm font-medium">AI精选</span>
</Button>
<span>AI精选</span>
</Link>
{/* 精选榜单 */}
<DropdownMenu open={rankingOpen} onOpenChange={setRankingOpen}>
@ -259,39 +253,30 @@ export function TopNavbar({
</Button>
{/* 无限画布 */}
<Button
variant="ghost"
size="sm"
className="flex items-center gap-1 h-8 px-3 text-white hover:bg-white/15 hover:text-white rounded-full transition-colors"
onClick={(e) => {
e.preventDefault();
e.stopPropagation();
<button
className="flex items-center gap-1 h-8 px-3 text-white hover:bg-white/15 hover:text-white rounded-full transition-colors text-sm font-medium"
onClick={() => {
const newId = crypto.randomUUID();
router.push(`/canvas/${newId}`);
router.refresh();
}}
type="button"
title="无限画布"
>
<LayoutGrid className="h-4 w-4 text-purple-400" />
<span className="text-sm font-medium">无限画布</span>
</Button>
<span>无限画布</span>
</button>
{/* 我的图册 */}
<Button
variant="ghost"
size="sm"
className="flex items-center gap-1 h-8 px-3 text-white hover:bg-white/15 hover:text-white rounded-full transition-colors"
onClick={(e) => {
e.preventDefault();
e.stopPropagation();
router.push("/gallery");
}}
type="button"
<Link
href="/gallery"
className="flex items-center gap-1 h-8 px-3 text-white hover:bg-white/15 hover:text-white rounded-full transition-colors text-sm font-medium"
title="我的图册"
onClick={() => router.refresh()}
>
<Images className="h-4 w-4" />
<span className="text-sm font-medium">我的图册</span>
</Button>
<span>我的图册</span>
</Link>
{/* 分隔线 (如果有链接或图册按钮,且是管理员) */}
{isAdmin && (
@ -300,20 +285,14 @@ export function TopNavbar({
{/* 系统设置(仅管理员可见)*/}
{isAdmin && (
<Button
variant="ghost"
size="sm"
className="h-8 w-8 p-0 text-white hover:bg-white/15 hover:text-white rounded-full"
onClick={(e) => {
e.preventDefault();
e.stopPropagation();
router.push("/settings");
}}
type="button"
<Link
href="/settings"
className="flex items-center justify-center h-8 w-8 text-white hover:bg-white/15 hover:text-white rounded-full"
title="系统设置"
onClick={() => router.refresh()}
>
<Settings className="h-4 w-4" />
</Button>
</Link>
)}
</div>