Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 19 additions & 3 deletions layouts/InAppUILayout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,23 @@ const InAppUILayout = ({ frontMatter, sourcePath, children }) => {
return Object.keys(languageMap)[0] as Language;
});

const selectedSdkContent = languageMap[selectedSdk];
// Sync selectedSdk when paths change (e.g., after hydration when router.query becomes available)
useEffect(() => {
const sdkFromPath = paths[1] as Language;
if (
sdkFromPath &&
languageMap[sdkFromPath] &&
sdkFromPath !== selectedSdk
) {
setSelectedSdk(sdkFromPath);
}
}, [paths, selectedSdk]);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

useEffect reverts SDK state during SDK switch

Medium Severity

The useEffect includes selectedSdk in its dependency array, causing it to fire when handleSdkChange updates state. Since router.push() is async, the URL path still reflects the old SDK at that point, so sdkFromPath !== selectedSdk evaluates to true and the effect calls setSelectedSdk(sdkFromPath), reverting the user's selection. Combined with effectiveSdk always prioritizing the path-derived SDK, the dropdown visibly snaps back to the previous SDK until the route transition completes, causing unnecessary re-renders and a brief UI flicker.

Additional Locations (1)
Fix in Cursor Fix in Web


// Derive SDK from path for breadcrumb computation to avoid timing issues with state
const sdkFromPath = paths[1] as Language;
const effectiveSdk =
sdkFromPath && languageMap[sdkFromPath] ? sdkFromPath : selectedSdk;
const selectedSdkContent = languageMap[effectiveSdk];
const allSidebarContent = [...IN_APP_UI_SIDEBAR, ...selectedSdkContent.items];

// @ts-expect-error we do get these, need to come back to breadcrumbs
Expand Down Expand Up @@ -179,7 +195,7 @@ const InAppUILayout = ({ frontMatter, sourcePath, children }) => {
mobileSidebar={
<MobileSidebar>
<InAppSidebar
selectedSdk={selectedSdk}
selectedSdk={effectiveSdk}
selectedSdkContent={selectedSdkContent}
handleSdkChange={handleSdkChange}
/>
Expand All @@ -192,7 +208,7 @@ const InAppUILayout = ({ frontMatter, sourcePath, children }) => {
<Sidebar.ScrollContainer scrollerRef={scrollerRef}>
<Stack direction="column" gap="2">
<InAppSidebar
selectedSdk={selectedSdk}
selectedSdk={effectiveSdk}
selectedSdkContent={selectedSdkContent}
handleSdkChange={handleSdkChange}
/>
Expand Down
57 changes: 33 additions & 24 deletions lib/content.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,30 +25,39 @@ export function getInAppSidebar(
// Get the deepest page that matches the paths
const { section, page } = depthFirstSidebarInfo(paths, allSidebarContent);

return {
breadcrumbs: [
{
slug: "in-app-ui",
title: "In-App UI",
path: "/in-app-ui",
},
{
slug: `/in-app-ui/${selectedSdkContent.value}`,
title: selectedSdkContent.title,
path: `/in-app-ui/${selectedSdkContent.value}`,
},
{
slug: `${section?.slug}`,
title: section?.title,
path: `${section?.slug}`,
},
{
slug: `${section?.slug}${page?.slug}`,
title: page?.title,
path: `${section?.slug}${page?.slug}`,
},
],
};
// Build breadcrumbs array conditionally to avoid "undefined" strings
const breadcrumbs: Array<{ slug: string; title: string; path: string }> = [
{
slug: "in-app-ui",
title: "In-App UI",
path: "/in-app-ui",
},
{
slug: `/in-app-ui/${selectedSdkContent.value}`,
title: selectedSdkContent.title,
path: `/in-app-ui/${selectedSdkContent.value}`,
},
];

// Only add section breadcrumb if section was found
if (section?.slug && section?.title) {
breadcrumbs.push({
slug: section.slug,
title: section.title,
path: section.slug,
});
}

// Only add page breadcrumb if both section and page were found
if (section?.slug && page?.slug && page?.title) {
breadcrumbs.push({
slug: `${section.slug}${page.slug}`,
title: page.title,
path: `${section.slug}${page.slug}`,
});
}

return { breadcrumbs };
}

export function depthFirstSidebarInfo(
Expand Down
Loading