-
-
Notifications
You must be signed in to change notification settings - Fork 3.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix: Selected framework in Code component #12496
base: main
Are you sure you want to change the base?
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
@@ -2,7 +2,7 @@ import { useSearchParams } from "next/navigation" | |||||||||
import { useRouter } from "next/router" | ||||||||||
import { useThemeConfig } from "nextra-theme-docs" | ||||||||||
import { Tabs } from "nextra/components" | ||||||||||
import React, { Children, useEffect, MouseEvent } from "react" | ||||||||||
import React, { Children, useEffect, MouseEvent, useState } from "react" | ||||||||||
|
||||||||||
interface ChildrenProps { | ||||||||||
children: React.ReactNode | ||||||||||
|
@@ -58,28 +58,61 @@ export function Code({ children }: ChildrenProps) { | |||||||||
|
||||||||||
const renderedFrameworks = withNextJsPages ? allFrameworks : baseFrameworks | ||||||||||
|
||||||||||
const [selectedFramework, setSelectedFramework] = useState<string>( | ||||||||||
Object.values(renderedFrameworks)[0] | ||||||||||
) | ||||||||||
|
||||||||||
const updateFrameworkStorage = (value: string): void => { | ||||||||||
const params = new URLSearchParams(searchParams?.toString()) | ||||||||||
params.set("framework", value) | ||||||||||
router.push(`${router.pathname}?${params.toString()}`) | ||||||||||
} | ||||||||||
|
||||||||||
const handleFrameworkChange = (framework: string) => { | ||||||||||
window.localStorage.setItem(AUTHJS_TAB_KEY, framework) | ||||||||||
window.dispatchEvent( | ||||||||||
new StorageEvent("storage", { | ||||||||||
key: AUTHJS_TAB_KEY, | ||||||||||
newValue: framework, | ||||||||||
}) | ||||||||||
) | ||||||||||
updateFrameworkStorage(parseParams(framework)) | ||||||||||
} | ||||||||||
|
||||||||||
const handleClickFramework = (event: MouseEvent<HTMLDivElement>) => { | ||||||||||
if (!(event.target instanceof HTMLButtonElement)) return | ||||||||||
const { textContent } = event.target as unknown as HTMLDivElement | ||||||||||
updateFrameworkStorage(parseParams(textContent!)) | ||||||||||
if (textContent) { | ||||||||||
handleFrameworkChange(textContent) | ||||||||||
} | ||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Check if the selected value is within |
||||||||||
} | ||||||||||
|
||||||||||
useEffect(() => { | ||||||||||
const length = Object.keys(renderedFrameworks).length | ||||||||||
function handleStorage(event: StorageEvent) { | ||||||||||
if ( | ||||||||||
event.key === AUTHJS_TAB_KEY && | ||||||||||
event.newValue && | ||||||||||
Object.values(renderedFrameworks).includes(event.newValue) | ||||||||||
) { | ||||||||||
setSelectedFramework(event.newValue) | ||||||||||
} | ||||||||||
} | ||||||||||
window.addEventListener("storage", handleStorage) | ||||||||||
return () => { | ||||||||||
window.removeEventListener("storage", handleStorage) | ||||||||||
} | ||||||||||
}, []) | ||||||||||
Comment on lines
93
to
+107
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this logic is unnecessary because changing the framework in the tabs will automatically update the selected framework, regardless of the active tab or whether you have instances of the page open in different windows on your computer. It will synchronize the updates. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You're correct; that was indeed the case when we used the storageKey prop in the Tabs component. The Tabs component managed the synchronization logic across all tabs. next-auth/docs/components/Code/index.tsx Lines 90 to 93 in 9d704a0
However, because the Tabs component relies on an index to track and sync the selected tab, this approach caused the issue we’re addressing. To resolve this, I extracted the synchronization logic from the Tabs component and adapted it to our use case. During this process, I reviewed the implementation of the Tabs component to understand its behavior and made targeted adjustments to ensure it works properly in our context, specifically by replacing the index-based tracking with framework names. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks for your explanation, that makes sense. When you remove the |
||||||||||
|
||||||||||
useEffect(() => { | ||||||||||
const getFrameworkStorage = window.localStorage.getItem(AUTHJS_TAB_KEY) | ||||||||||
const indexFramework = parseInt(getFrameworkStorage ?? "0") % length | ||||||||||
if (!getFrameworkStorage) { | ||||||||||
window.localStorage.setItem(AUTHJS_TAB_KEY, "0") | ||||||||||
handleFrameworkChange(Object.values(renderedFrameworks)[0]) | ||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You can simply use the value |
||||||||||
} else if ( | ||||||||||
Object.values(renderedFrameworks).includes(getFrameworkStorage) | ||||||||||
) { | ||||||||||
setSelectedFramework(getFrameworkStorage) | ||||||||||
updateFrameworkStorage(parseParams(getFrameworkStorage)) | ||||||||||
} | ||||||||||
updateFrameworkStorage( | ||||||||||
parseParams(Object.values(renderedFrameworks)[indexFramework]) | ||||||||||
) | ||||||||||
}, [router.pathname, renderedFrameworks]) | ||||||||||
|
||||||||||
return ( | ||||||||||
|
@@ -88,7 +121,9 @@ export function Code({ children }: ChildrenProps) { | |||||||||
onClick={handleClickFramework} | ||||||||||
> | ||||||||||
<Tabs | ||||||||||
storageKey={AUTHJS_TAB_KEY} | ||||||||||
selectedIndex={Object.values(renderedFrameworks).indexOf( | ||||||||||
selectedFramework | ||||||||||
)} | ||||||||||
items={Object.values(renderedFrameworks)} | ||||||||||
> | ||||||||||
{Object.keys(renderedFrameworks).map((f) => { | ||||||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To avoid repeating the use of
parseParams
throughout the code, please move it to theupdateFrameworkStorage
function.