ActivityChartWrapper 组件
概述
ActivityChartWrapper 是 ActivityChart 的包装组件,处理 URL 查询参数与活动图表的交互,实现日期筛选功能。
文件路径
src/components/user/activity-chart-wrapper.tsx
功能特性
- URL 同步: 将选中的日期同步到 URL 查询参数
- 自动切换 Tab: 筛选时自动切换到 Prompts 标签
- 页面重置: 筛选时重置到第 1 页
- 无滚动跳转: 更新 URL 时不滚动页面
接口定义
interface ActivityChartWrapperProps {
data: { date: string; count: number }[]; // 活动数据
locale?: string; // 语言区域
}
使用示例
import { ActivityChartWrapper } from "@/components/user/activity-chart-wrapper";
export default function UserProfile({ activityData }: { activityData: ActivityData[] }) {
return (
<ActivityChartWrapper
data={activityData}
locale="zh-CN"
/>
);
}
工作流程
用户点击日期
↓
读取当前 URL 查询参数
↓
设置/删除 date 参数
↓
删除 page 参数(重置分页)
↓
设置 tab=prompts(切换到 Prompts)
↓
更新 URL(不滚动)
↓
触发页面数据重新获取
URL 参数处理
选择日期
当前: ?tab=prompts&page=2
点击: 2024-01-15
结果: ?tab=prompts&date=2024-01-15
取消选择
当前: ?tab=prompts&date=2024-01-15
再次点击: 2024-01-15
结果: ?tab=prompts(date 参数被移除)
实现代码
const handleDateClick = useCallback((date: string | null) => {
const params = new URLSearchParams(searchParams?.toString() || "");
if (date) {
params.set("date", date);
params.delete("page"); // 重置分页
} else {
params.delete("date");
}
// 切换到 Prompts 标签
if (date) {
params.set("tab", "prompts");
}
const newUrl = `?${params.toString()}`;
router.push(newUrl, { scroll: false });
}, [router, searchParams]);
依赖
next/navigation-useRouter,useSearchParams./activity-chart- 底层图表组件
与 ActivityChart 的关系
ActivityChartWrapper
├── 处理 URL 参数
├── 管理路由状态
└── ActivityChart
├── 渲染热力图
└── 触发 onDateClick
注意事项
- 该组件必须在 Next.js App Router 中使用
- 依赖
searchParams读取当前 URL 状态 - 使用
scroll: false防止页面跳动 - 父页面需要根据
date参数筛选数据 - 服务端组件获取数据,客户端组件处理交互
服务端集成
在服务端组件中使用:
// page.tsx (Server Component)
export default async function ProfilePage({
searchParams
}: {
searchParams: { date?: string; tab?: string; page?: string }
}) {
const date = searchParams.date;
const page = parseInt(searchParams.page || "1");
// 根据日期筛选数据
const prompts = await getPrompts({
date,
page
});
const activityData = await getActivityData();
return (
<>
<ActivityChartWrapper data={activityData} />
<PromptList prompts={prompts} />
</>
);
}