Skip to content

Commit 6ba0f42

Browse files
committed
fix: framework switcher
1 parent 994eb5d commit 6ba0f42

7 files changed

Lines changed: 54 additions & 23 deletions

File tree

src/components/FrameworkSelect.tsx

Lines changed: 33 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,16 @@
11
import * as React from 'react'
22
import { create } from 'zustand'
3-
import { useNavigate, useParams } from '@tanstack/react-router'
3+
import { useLocation, useNavigate, useParams } from '@tanstack/react-router'
4+
import { useQueryClient } from '@tanstack/react-query'
45
import { Select } from './Select'
56
import { Framework, getLibrary, LibraryId } from '~/libraries'
67
import { getFrameworkOptions } from '~/libraries/frameworks'
7-
import { useCurrentUserQuery } from '~/hooks/useCurrentUser'
8+
import {
9+
currentUserQueryOptions,
10+
useCurrentUserQuery,
11+
} from '~/hooks/useCurrentUser'
812
import { updateLastUsedFramework } from '~/utils/users.functions'
13+
import type { User } from '~/db/types'
914

1015
function persistFrameworkToServer(framework: string) {
1116
void updateLastUsedFramework({ data: { framework } }).catch(() => {
@@ -72,18 +77,22 @@ export function getStoredFrameworkPreference(): string | undefined {
7277
*/
7378
export function usePersistFrameworkPreference() {
7479
const userQuery = useCurrentUserQuery()
80+
const queryClient = useQueryClient()
7581
const localCurrentFramework = useLocalCurrentFramework()
7682

7783
return React.useCallback(
7884
(framework: string) => {
7985
// Always update localStorage as fallback
8086
localCurrentFramework.setCurrentFramework(framework)
87+
queryClient.setQueryData(currentUserQueryOptions.queryKey, (user) =>
88+
user ? { ...user, lastUsedFramework: framework } : user,
89+
)
8190
// Update DB for logged-in users (fire-and-forget)
8291
if (userQuery.data) {
8392
persistFrameworkToServer(framework)
8493
}
8594
},
86-
[localCurrentFramework, userQuery.data],
95+
[localCurrentFramework, queryClient, userQuery.data],
8796
)
8897
}
8998

@@ -114,7 +123,9 @@ function useFrameworkConfig({ frameworks }: { frameworks: Framework[] }) {
114123
*/
115124
export function useCurrentFramework(frameworks: Framework[]) {
116125
const navigate = useNavigate()
126+
const location = useLocation()
117127
const userQuery = useCurrentUserQuery()
128+
const queryClient = useQueryClient()
118129

119130
const { framework: paramsFramework } = useParams({
120131
strict: false,
@@ -133,17 +144,32 @@ export function useCurrentFramework(frameworks: Framework[]) {
133144

134145
const setFramework = React.useCallback(
135146
(framework: string) => {
136-
navigate({
137-
params: { framework } as any,
138-
})
139147
// Always update localStorage as fallback
140148
localCurrentFramework.setCurrentFramework(framework)
149+
queryClient.setQueryData(currentUserQueryOptions.queryKey, (user) =>
150+
user ? { ...user, lastUsedFramework: framework } : user,
151+
)
152+
const nextPathname = location.pathname.replace(
153+
/(\/docs\/framework\/)[^/]+/,
154+
`$1${framework}`,
155+
)
156+
if (nextPathname !== location.pathname) {
157+
const queryString = window.location.search
158+
const hash = window.location.hash
159+
navigate({ href: `${nextPathname}${queryString}${hash}` })
160+
}
141161
// Update DB for logged-in users (fire-and-forget)
142162
if (userQuery.data) {
143163
persistFrameworkToServer(framework)
144164
}
145165
},
146-
[localCurrentFramework, navigate, userQuery.data],
166+
[
167+
localCurrentFramework,
168+
location.pathname,
169+
navigate,
170+
queryClient,
171+
userQuery.data,
172+
],
147173
)
148174

149175
React.useEffect(() => {

src/components/account/AccountProfilePictureSection.client.tsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { useToast } from '~/components/ToastProvider'
77
import { Button } from '~/ui'
88
import { removeProfileImage, revertProfileImage } from '~/utils/users.functions'
99
import { useUploadThing } from '~/utils/uploadthing.client'
10+
import { currentUserQueryOptions } from '~/hooks/useCurrentUser'
1011

1112
type AccountProfileUser = {
1213
image?: string | null
@@ -33,7 +34,7 @@ export function AccountProfilePictureSection({
3334
const { startUpload } = useUploadThing('avatarUploader', {
3435
onClientUploadComplete: () => {
3536
setIsUploading(false)
36-
queryClient.invalidateQueries({ queryKey: ['currentUser'] })
37+
queryClient.invalidateQueries(currentUserQueryOptions)
3738
notify(
3839
<div>
3940
<div className="font-medium">Profile picture updated</div>
@@ -81,7 +82,7 @@ export function AccountProfilePictureSection({
8182
setIsReverting(true)
8283
try {
8384
await revertProfileImage()
84-
queryClient.invalidateQueries({ queryKey: ['currentUser'] })
85+
queryClient.invalidateQueries(currentUserQueryOptions)
8586
notify(
8687
<div>
8788
<div className="font-medium">Profile picture reverted</div>
@@ -108,7 +109,7 @@ export function AccountProfilePictureSection({
108109
setIsRemoving(true)
109110
try {
110111
await removeProfileImage()
111-
queryClient.invalidateQueries({ queryKey: ['currentUser'] })
112+
queryClient.invalidateQueries(currentUserQueryOptions)
112113
notify(
113114
<div>
114115
<div className="font-medium">Profile picture removed</div>

src/components/game/ui/DebugPanel.tsx

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,16 @@ import {
55
PARTNER_UPGRADE_ORDER,
66
SHOWCASE_UPGRADE_ORDER,
77
} from '../utils/upgrades'
8+
import { currentUserQueryOptions } from '~/hooks/useCurrentUser'
89

910
const UPGRADE_ORDER = [...PARTNER_UPGRADE_ORDER, ...SHOWCASE_UPGRADE_ORDER]
10-
import { getCurrentUser } from '~/utils/auth.functions'
1111

1212
export function DebugPanel() {
1313
const [isCollapsed, setIsCollapsed] = useState(true)
1414

1515
// Fetch user directly without route context dependency
1616
const userQuery = useQuery({
17-
queryKey: ['currentUser'],
18-
queryFn: () => getCurrentUser(),
17+
...currentUserQueryOptions,
1918
staleTime: 30 * 1000,
2019
})
2120

src/contexts/LoginModalContext.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import * as React from 'react'
44
import { useQueryClient } from '@tanstack/react-query'
55
import { LoginModal } from '~/components/LoginModal'
6+
import { currentUserQueryOptions } from '~/hooks/useCurrentUser'
67

78
interface LoginModalContextValue {
89
openLoginModal: (options?: { onSuccess?: () => void }) => void
@@ -47,7 +48,7 @@ export function LoginModalProvider({ children }: LoginModalProviderProps) {
4748
const handleMessage = (event: MessageEvent) => {
4849
if (event.origin !== window.location.origin) return
4950
if (event.data?.type === 'TANSTACK_AUTH_SUCCESS') {
50-
queryClient.invalidateQueries({ queryKey: ['currentUser'] })
51+
queryClient.invalidateQueries(currentUserQueryOptions)
5152
const onSuccess = pendingOnSuccessRef.current
5253
setIsOpen(false)
5354
pendingOnSuccessRef.current = undefined

src/hooks/useCurrentUser.ts

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,23 @@
1-
import { useQuery } from '@tanstack/react-query'
1+
import { useQuery, queryOptions } from '@tanstack/react-query'
22
import { useRouteContext } from '@tanstack/react-router'
33
import { getCurrentUser } from '~/utils/auth.functions'
44

5+
export const currentUserQueryOptions = queryOptions({
6+
queryKey: ['currentUser'],
7+
queryFn: async () => {
8+
return getCurrentUser()
9+
},
10+
staleTime: 5 * 1000,
11+
})
12+
513
export function useCurrentUserQuery() {
614
// Get user from route context (set in beforeLoad)
715
const routeContext = useRouteContext({ strict: false })
816
const contextUser = routeContext?.user
917

1018
return useQuery({
11-
queryKey: ['currentUser'],
12-
queryFn: async () => {
13-
return getCurrentUser()
14-
},
19+
...currentUserQueryOptions,
1520
initialData: contextUser,
16-
staleTime: 5 * 1000,
1721
})
1822
}
1923

src/libraries/libraries.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ export const query: LibrarySlim = {
1313
tagline:
1414
'Powerful asynchronous state management, server-state utilities and data fetching',
1515
description:
16-
'Powerful asynchronous state management, server-state utilities and data fetching. Fetch, cache, update, and wrangle all forms of async data in your TS/JS, React, Vue, Solid, Svelte & Angular applications all without touching any "global state"',
16+
'Powerful asynchronous state management, server-state utilities and data fetching. Fetch, cache, update, and wrangle all forms of async data in your TS/JS, React, Vue, Solid, Svelte, Angular & Lit applications all without touching any "global state"',
1717
bgStyle: 'bg-red-500',
1818
borderStyle: 'border-red-500/50',
1919
textStyle: 'text-red-500',
@@ -23,7 +23,7 @@ export const query: LibrarySlim = {
2323
bgRadial: 'from-red-500 via-red-500/60 to-transparent',
2424
badge: undefined,
2525
repo: 'tanstack/query',
26-
frameworks: ['react', 'preact', 'solid', 'vue', 'svelte', 'angular'],
26+
frameworks: ['react', 'preact', 'solid', 'vue', 'svelte', 'angular', 'lit'],
2727
latestVersion: 'v5',
2828
latestBranch: 'main',
2929
availableVersions: ['v5', 'v4', 'v3'],

src/libraries/query.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ const textStyles = 'text-red-500 dark:text-red-400'
88
export const queryProject = {
99
...query,
1010
description:
11-
'Powerful asynchronous state management, server-state utilities and data fetching. Fetch, cache, update, and wrangle all forms of async data in your TS/JS, React, Vue, Solid, Svelte & Angular applications all without touching any "global state"',
11+
'Powerful asynchronous state management, server-state utilities and data fetching. Fetch, cache, update, and wrangle all forms of async data in your TS/JS, React, Vue, Solid, Svelte, Angular & Lit applications all without touching any "global state"',
1212
latestBranch: 'main',
1313
bgRadial: 'from-red-500 via-red-500/60 to-transparent',
1414
textColor: 'text-amber-500',

0 commit comments

Comments
 (0)