-
Notifications
You must be signed in to change notification settings - Fork 10
Description
Problem
The quick navigation pills (module buttons in the top-right) navigate to a segment but then immediately bounce back to the previous segment.
Root Cause
The SegmentContext (src/routes/learn/-components/segment-context.tsx) duplicates URL state and causes navigation issues.
How it works currently:
- Context stores
currentSegmentIdin React state - Every navigation click must call
setCurrentSegmentId()before/during navigation - A
useEffectin_layout.tsxwatches context and callsnavigate()if there's a mismatch
The bug:
ModulePillButton in quick-navigation-bar.tsx uses <Link> to navigate but doesn't call setCurrentSegmentId(). The useEffect sees the mismatch (context has old ID, URL has new segment) and navigates back.
Why the context is redundant:
- URL is already the source of truth - TanStack Router handles navigation, loader fetches segment data
- Components get
currentSegmentIdas a prop from loader data (segment.id), not from context - Only
_layout.tsxreads from context - and only for the sync useEffect - The context is just an indirect way to call
navigate()
Proposed Solutions
Option A: Remove context, use direct navigation
Delete SegmentContext entirely and use navigate() or <Link> directly:
// Before (VideoControls):
setCurrentSegmentId(nextSegment.id);
// After:
navigate({ to: "/learn/$slug", params: { slug: nextSegment.slug } });For <Link> components - just remove the onClick handlers that call setCurrentSegmentId().
Pros: Simpler, URL is single source of truth
Cons: Components need access to useNavigate() or use <Link>
Option B: Keep context, move navigation logic into it
Make the context handle navigation internally so components don't need prop drilling:
// segment-context.tsx
export function SegmentProvider({ children }: { children: React.ReactNode }) {
const navigate = useNavigate();
const navigateToSegment = useCallback((segmentSlug: string) => {
navigate({ to: "/learn/$slug", params: { slug: segmentSlug } });
}, [navigate]);
return (
<SegmentContext.Provider value={{ navigateToSegment }}>
{children}
</SegmentContext.Provider>
);
}
// Usage in components:
const { navigateToSegment } = useSegment();
navigateToSegment(nextSegment.slug);Pros: No prop drilling for navigation, centralized navigation logic
Cons: Extra abstraction layer
Files affected:
src/routes/learn/-components/segment-context.tsxsrc/routes/learn/$slug/_layout.tsxsrc/routes/learn/$slug/-components/video-controls.tsxsrc/routes/learn/$slug/-components/quick-navigation-bar.tsxsrc/routes/learn/-components/navigation-items.tsxsrc/routes/learn/-components/desktop-navigation.tsx
