Fix TOC showing headings from previous article

The TOC was displaying sections from previously viewed articles when
navigating between posts. This happened because the DOM query for
headings ran before Next.js finished updating the page content.

Changes to components/post-toc.tsx:
- Clear items and activeId immediately when pathname changes
- Add 50ms delay before querying DOM for new headings
- Properly handle IntersectionObserver cleanup with timeout

This ensures the TOC always shows the correct headings for the
current article, not the previous one.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-11-20 23:29:17 +08:00
parent 5d226a2969
commit e2f9c9d556

View File

@@ -19,6 +19,14 @@ export function PostToc({ onLinkClick }: { onLinkClick?: () => void }) {
const pathname = usePathname();
useEffect(() => {
// Clear items immediately when pathname changes
setItems([]);
setActiveId(null);
let observer: IntersectionObserver | null = null;
// Small delay to ensure DOM has been updated with new article content
const timeoutId = setTimeout(() => {
const headings = Array.from(
document.querySelectorAll<HTMLElement>('article h2, article h3')
);
@@ -31,7 +39,7 @@ export function PostToc({ onLinkClick }: { onLinkClick?: () => void }) {
}));
setItems(mapped);
const observer = new IntersectionObserver(
observer = new IntersectionObserver(
(entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
@@ -49,9 +57,15 @@ export function PostToc({ onLinkClick }: { onLinkClick?: () => void }) {
}
);
headings.forEach((el) => observer.observe(el));
headings.forEach((el) => observer?.observe(el));
}, 50); // 50ms delay to ensure DOM is updated
return () => observer.disconnect();
return () => {
clearTimeout(timeoutId);
if (observer) {
observer.disconnect();
}
};
}, [pathname]);
useEffect(() => {