Fix TOC showing wrong headings across navigation
Problem: Table of Contents displayed headings from previously viewed articles when navigating between posts via client-side routing. Root cause: PostToc component's useEffect with empty dependency array only ran once on mount, so it retained stale heading data when React reused the component instance during navigation. Solution: Add contentKey prop flow: - Blog/page routes pass slug to PostLayout - PostLayout passes contentKey as key prop to PostToc instances - React remounts PostToc when key changes, rebuilding TOC correctly Files changed: - components/post-layout.tsx: Add contentKey prop and key forwarding - app/blog/[slug]/page.tsx: Pass slug as contentKey - app/pages/[slug]/page.tsx: Pass slug as contentKey
This commit is contained in:
@@ -79,7 +79,7 @@ export default async function BlogPostPage({ params }: Props) {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<ReadingProgress />
|
<ReadingProgress />
|
||||||
<PostLayout hasToc={hasToc}>
|
<PostLayout hasToc={hasToc} contentKey={slug}>
|
||||||
<div className="space-y-8">
|
<div className="space-y-8">
|
||||||
{/* Main content area for Pagefind indexing */}
|
{/* Main content area for Pagefind indexing */}
|
||||||
<div data-pagefind-body>
|
<div data-pagefind-body>
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ export default async function StaticPage({ params }: Props) {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<ReadingProgress />
|
<ReadingProgress />
|
||||||
<PostLayout hasToc={hasToc}>
|
<PostLayout hasToc={hasToc} contentKey={slug}>
|
||||||
<div className="space-y-8">
|
<div className="space-y-8">
|
||||||
<SectionDivider>
|
<SectionDivider>
|
||||||
<ScrollReveal>
|
<ScrollReveal>
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ function cn(...inputs: ClassValue[]) {
|
|||||||
return twMerge(clsx(inputs));
|
return twMerge(clsx(inputs));
|
||||||
}
|
}
|
||||||
|
|
||||||
export function PostLayout({ children, hasToc = true }: { children: React.ReactNode; hasToc?: boolean }) {
|
export function PostLayout({ children, hasToc = true, contentKey }: { children: React.ReactNode; hasToc?: boolean; contentKey?: string }) {
|
||||||
const [isTocOpen, setIsTocOpen] = useState(hasToc);
|
const [isTocOpen, setIsTocOpen] = useState(hasToc);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -43,7 +43,7 @@ export function PostLayout({ children, hasToc = true }: { children: React.ReactN
|
|||||||
transition={{ duration: 0.3 }}
|
transition={{ duration: 0.3 }}
|
||||||
className="h-full overflow-y-auto pr-2"
|
className="h-full overflow-y-auto pr-2"
|
||||||
>
|
>
|
||||||
<PostToc />
|
<PostToc key={contentKey} />
|
||||||
</motion.div>
|
</motion.div>
|
||||||
)}
|
)}
|
||||||
</AnimatePresence>
|
</AnimatePresence>
|
||||||
@@ -62,7 +62,7 @@ export function PostLayout({ children, hasToc = true }: { children: React.ReactN
|
|||||||
className="fixed bottom-24 right-4 z-40 w-72 rounded-2xl border border-white/20 bg-white/90 p-6 shadow-2xl backdrop-blur-xl dark:border-white/10 dark:bg-slate-900/90 lg:hidden"
|
className="fixed bottom-24 right-4 z-40 w-72 rounded-2xl border border-white/20 bg-white/90 p-6 shadow-2xl backdrop-blur-xl dark:border-white/10 dark:bg-slate-900/90 lg:hidden"
|
||||||
>
|
>
|
||||||
<div className="max-h-[60vh] overflow-y-auto">
|
<div className="max-h-[60vh] overflow-y-auto">
|
||||||
<PostToc onLinkClick={() => setIsTocOpen(false)} />
|
<PostToc key={contentKey} onLinkClick={() => setIsTocOpen(false)} />
|
||||||
</div>
|
</div>
|
||||||
</motion.div>
|
</motion.div>
|
||||||
)}
|
)}
|
||||||
|
|||||||
Reference in New Issue
Block a user