Wrap useProfile with ProfileProvider and refactor to use React Context

This commit is contained in:
MartinBraquet
2026-04-02 15:00:48 +02:00
parent df775e9aa3
commit ff23a8c1bc
2 changed files with 36 additions and 18 deletions

View File

@@ -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<Row<'profiles'> | 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<OwnProfile | typeof MISSING>(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 <ProfileContext.Provider value={profile}>{children}</ProfileContext.Provider>
}
export const useProfileByUser = (user: User | undefined) => {
const userId = user?.id
const [profile, setProfile] = usePersistentInMemoryState<Profile | undefined | null>(

View File

@@ -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<PageProps>) {
<I18nContext.Provider value={{locale, setLocale}}>
<ErrorBoundary>
<AuthProvider serverUser={pageProps.auth}>
<ChoicesProvider>
<PinnedQuestionIdsProvider>
<HiddenProfilesProvider>
<WebPush />
<AndroidPush />
<Component {...pageProps} />
</HiddenProfilesProvider>
</PinnedQuestionIdsProvider>
</ChoicesProvider>
<ProfileProvider>
<ChoicesProvider>
<PinnedQuestionIdsProvider>
<HiddenProfilesProvider>
<WebPush />
<AndroidPush />
<Component {...pageProps} />
</HiddenProfilesProvider>
</PinnedQuestionIdsProvider>
</ChoicesProvider>
</ProfileProvider>
</AuthProvider>
</ErrorBoundary>
</I18nContext.Provider>