diff --git a/src/components/FrameworkSelect.tsx b/src/components/FrameworkSelect.tsx index 21069e686..65f7a65e4 100644 --- a/src/components/FrameworkSelect.tsx +++ b/src/components/FrameworkSelect.tsx @@ -1,10 +1,14 @@ import * as React from 'react' import { create } from 'zustand' import { useNavigate, useParams } from '@tanstack/react-router' +import { useQueryClient } from '@tanstack/react-query' import { Select } from './Select' import { Framework, getLibrary, LibraryId } from '~/libraries' import { getFrameworkOptions } from '~/libraries/frameworks' -import { useCurrentUserQuery } from '~/hooks/useCurrentUser' +import { + currentUserQueryOptions, + useCurrentUserQuery, +} from '~/hooks/useCurrentUser' import { updateLastUsedFramework } from '~/utils/users.functions' function persistFrameworkToServer(framework: string) { @@ -72,18 +76,22 @@ export function getStoredFrameworkPreference(): string | undefined { */ export function usePersistFrameworkPreference() { const userQuery = useCurrentUserQuery() + const queryClient = useQueryClient() const localCurrentFramework = useLocalCurrentFramework() return React.useCallback( (framework: string) => { // Always update localStorage as fallback localCurrentFramework.setCurrentFramework(framework) + queryClient.setQueryData(currentUserQueryOptions.queryKey, (user) => + user ? { ...user, lastUsedFramework: framework } : user, + ) // Update DB for logged-in users (fire-and-forget) if (userQuery.data) { persistFrameworkToServer(framework) } }, - [localCurrentFramework, userQuery.data], + [localCurrentFramework, queryClient, userQuery.data], ) } @@ -115,6 +123,7 @@ function useFrameworkConfig({ frameworks }: { frameworks: Framework[] }) { export function useCurrentFramework(frameworks: Framework[]) { const navigate = useNavigate() const userQuery = useCurrentUserQuery() + const queryClient = useQueryClient() const { framework: paramsFramework } = useParams({ strict: false, @@ -138,12 +147,16 @@ export function useCurrentFramework(frameworks: Framework[]) { }) // Always update localStorage as fallback localCurrentFramework.setCurrentFramework(framework) + queryClient.setQueryData(currentUserQueryOptions.queryKey, (user) => + user ? { ...user, lastUsedFramework: framework } : user, + ) + // Update DB for logged-in users (fire-and-forget) if (userQuery.data) { persistFrameworkToServer(framework) } }, - [localCurrentFramework, navigate, userQuery.data], + [localCurrentFramework, navigate, queryClient, userQuery.data], ) React.useEffect(() => { diff --git a/src/components/Select.tsx b/src/components/Select.tsx index 286262337..5579a2dbf 100644 --- a/src/components/Select.tsx +++ b/src/components/Select.tsx @@ -67,7 +67,7 @@ export function Select({ - + {available.map((option) => ( { setIsUploading(false) - queryClient.invalidateQueries({ queryKey: ['currentUser'] }) + queryClient.invalidateQueries(currentUserQueryOptions) notify(
Profile picture updated
@@ -81,7 +82,7 @@ export function AccountProfilePictureSection({ setIsReverting(true) try { await revertProfileImage() - queryClient.invalidateQueries({ queryKey: ['currentUser'] }) + queryClient.invalidateQueries(currentUserQueryOptions) notify(
Profile picture reverted
@@ -108,7 +109,7 @@ export function AccountProfilePictureSection({ setIsRemoving(true) try { await removeProfileImage() - queryClient.invalidateQueries({ queryKey: ['currentUser'] }) + queryClient.invalidateQueries(currentUserQueryOptions) notify(
Profile picture removed
diff --git a/src/components/game/ui/DebugPanel.tsx b/src/components/game/ui/DebugPanel.tsx index 3b1b6136b..f03fec78f 100644 --- a/src/components/game/ui/DebugPanel.tsx +++ b/src/components/game/ui/DebugPanel.tsx @@ -5,17 +5,16 @@ import { PARTNER_UPGRADE_ORDER, SHOWCASE_UPGRADE_ORDER, } from '../utils/upgrades' +import { currentUserQueryOptions } from '~/hooks/useCurrentUser' const UPGRADE_ORDER = [...PARTNER_UPGRADE_ORDER, ...SHOWCASE_UPGRADE_ORDER] -import { getCurrentUser } from '~/utils/auth.functions' export function DebugPanel() { const [isCollapsed, setIsCollapsed] = useState(true) // Fetch user directly without route context dependency const userQuery = useQuery({ - queryKey: ['currentUser'], - queryFn: () => getCurrentUser(), + ...currentUserQueryOptions, staleTime: 30 * 1000, }) diff --git a/src/contexts/LoginModalContext.tsx b/src/contexts/LoginModalContext.tsx index eeba99647..694d124e2 100644 --- a/src/contexts/LoginModalContext.tsx +++ b/src/contexts/LoginModalContext.tsx @@ -3,6 +3,7 @@ import * as React from 'react' import { useQueryClient } from '@tanstack/react-query' import { LoginModal } from '~/components/LoginModal' +import { currentUserQueryOptions } from '~/hooks/useCurrentUser' interface LoginModalContextValue { openLoginModal: (options?: { onSuccess?: () => void }) => void @@ -47,7 +48,7 @@ export function LoginModalProvider({ children }: LoginModalProviderProps) { const handleMessage = (event: MessageEvent) => { if (event.origin !== window.location.origin) return if (event.data?.type === 'TANSTACK_AUTH_SUCCESS') { - queryClient.invalidateQueries({ queryKey: ['currentUser'] }) + queryClient.invalidateQueries(currentUserQueryOptions) const onSuccess = pendingOnSuccessRef.current setIsOpen(false) pendingOnSuccessRef.current = undefined diff --git a/src/hooks/useCurrentUser.ts b/src/hooks/useCurrentUser.ts index 05e259057..6c7b0abfc 100644 --- a/src/hooks/useCurrentUser.ts +++ b/src/hooks/useCurrentUser.ts @@ -1,19 +1,23 @@ -import { useQuery } from '@tanstack/react-query' +import { useQuery, queryOptions } from '@tanstack/react-query' import { useRouteContext } from '@tanstack/react-router' import { getCurrentUser } from '~/utils/auth.functions' +export const currentUserQueryOptions = queryOptions({ + queryKey: ['currentUser'], + queryFn: async () => { + return getCurrentUser() + }, + staleTime: 5 * 1000, +}) + export function useCurrentUserQuery() { // Get user from route context (set in beforeLoad) const routeContext = useRouteContext({ strict: false }) const contextUser = routeContext?.user return useQuery({ - queryKey: ['currentUser'], - queryFn: async () => { - return getCurrentUser() - }, + ...currentUserQueryOptions, initialData: contextUser, - staleTime: 5 * 1000, }) } diff --git a/src/libraries/libraries.ts b/src/libraries/libraries.ts index 9f596ecfc..d296b1299 100644 --- a/src/libraries/libraries.ts +++ b/src/libraries/libraries.ts @@ -13,7 +13,7 @@ export const query: LibrarySlim = { tagline: 'Powerful asynchronous state management, server-state utilities and data fetching', description: - '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"', + '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"', bgStyle: 'bg-red-500', borderStyle: 'border-red-500/50', textStyle: 'text-red-500', @@ -23,7 +23,7 @@ export const query: LibrarySlim = { bgRadial: 'from-red-500 via-red-500/60 to-transparent', badge: undefined, repo: 'tanstack/query', - frameworks: ['react', 'preact', 'solid', 'vue', 'svelte', 'angular'], + frameworks: ['react', 'preact', 'solid', 'vue', 'svelte', 'angular', 'lit'], latestVersion: 'v5', latestBranch: 'main', availableVersions: ['v5', 'v4', 'v3'], diff --git a/src/libraries/query.tsx b/src/libraries/query.tsx index de697d2a2..2253a63b0 100644 --- a/src/libraries/query.tsx +++ b/src/libraries/query.tsx @@ -8,7 +8,7 @@ const textStyles = 'text-red-500 dark:text-red-400' export const queryProject = { ...query, description: - '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"', + '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"', latestBranch: 'main', bgRadial: 'from-red-500 via-red-500/60 to-transparent', textColor: 'text-amber-500',