From ff23a8c1bc16e2709beb5c9489002a7662bcc1ed Mon Sep 17 00:00:00 2001 From: MartinBraquet Date: Thu, 2 Apr 2026 15:00:48 +0200 Subject: [PATCH] Wrap `useProfile` with `ProfileProvider` and refactor to use React Context --- web/hooks/{use-profile.ts => use-profile.tsx} | 33 ++++++++++++++----- web/pages/_app.tsx | 21 +++++++----- 2 files changed, 36 insertions(+), 18 deletions(-) rename web/hooks/{use-profile.ts => use-profile.tsx} (72%) diff --git a/web/hooks/use-profile.ts b/web/hooks/use-profile.tsx similarity index 72% rename from web/hooks/use-profile.ts rename to web/hooks/use-profile.tsx index faf35cd6..6f674450 100644 --- a/web/hooks/use-profile.ts +++ b/web/hooks/use-profile.tsx @@ -6,13 +6,15 @@ import { } from 'common/profiles/profile' import {Row} from 'common/supabase/utils' import {User} from 'common/user' -import {useEffect} from 'react' +import {createContext, ReactNode, useContext, useEffect} from 'react' import {usePersistentInMemoryState} from 'web/hooks/use-persistent-in-memory-state' import {usePersistentLocalState} from 'web/hooks/use-persistent-local-state' import {useUser} from 'web/hooks/use-user' import {db} from 'web/lib/supabase/db' -export const useProfile = () => { +type OwnProfile = (Row<'profiles'> & {user: User}) | null | undefined + +const useOwnProfile = (): OwnProfile => { const user = useUser() const [profile, setProfile] = usePersistentLocalState | undefined | null>( undefined, @@ -20,13 +22,11 @@ export const useProfile = () => { ) const refreshProfile = () => { - if (user) { - // logger.debug('Refreshing profile in useProfile for', user?.username, profile); - getProfileRowWithFrontendSupabase(user.id, db).then((profile) => { - if (!profile) setProfile(null) - else setProfile(profile) - }) - } + if (!user?.id) return + debug('Refreshing own profile for', user.username) + getProfileRowWithFrontendSupabase(user.id, db).then((p) => { + setProfile(p ?? null) + }) } useEffect(() => { @@ -36,6 +36,21 @@ export const useProfile = () => { return user && profile ? {...profile, user} : profile === null ? null : undefined } +const MISSING = Symbol('missing') + +const ProfileContext = createContext(MISSING) + +export const useProfile = () => { + const ctx = useContext(ProfileContext) + if (ctx === MISSING) throw new Error('useProfile must be used within a ProfileProvider') + return ctx as OwnProfile +} + +export const ProfileProvider = ({children}: {children: ReactNode}) => { + const profile = useOwnProfile() + return {children} +} + export const useProfileByUser = (user: User | undefined) => { const userId = user?.id const [profile, setProfile] = usePersistentInMemoryState( diff --git a/web/pages/_app.tsx b/web/pages/_app.tsx index ab5f25be..e4394528 100644 --- a/web/pages/_app.tsx +++ b/web/pages/_app.tsx @@ -25,6 +25,7 @@ import {useFontPreferenceManager} from 'web/hooks/use-font-preference' import {useHasLoaded} from 'web/hooks/use-has-loaded' import {HiddenProfilesProvider} from 'web/hooks/use-hidden-profiles' import {PinnedQuestionIdsProvider} from 'web/hooks/use-pinned-question-ids' +import {ProfileProvider} from 'web/hooks/use-profile' import {updateStatusBar} from 'web/hooks/use-theme' import {updateBackendLocale} from 'web/lib/api' import {DAYJS_LOCALE_IMPORTS, registerDatePickerLocale} from 'web/lib/dayjs' @@ -208,15 +209,17 @@ function MyApp(props: AppProps) { - - - - - - - - - + + + + + + + + + + +