Currently, unless a locale is present in the URL search params, the locale context is instantiated using the default locale until prefs load in client-side. This causes the locale selector to briefly render in with the incorrect (default) locale before being replaced by the proper locale of the request. For example, if the default locale is `en`, and the page is requested in `es`, the locale selector will flash with English before changing to the correct locale, even though the page data itself is properly loaded in Spanish. This is especially evident within slow networks. The fix is to query the user's locale preference server-side and thread it into the locale provider to initialize state. Because search params are not available within server layouts, we cannot pass the locale param in the same way, so we rely on the provider itself to read them from the `useSearchParams` hook. If present, this takes precedence over the user's preference if it exists. Since the root page also queries the user's locale preference to determine the proper locale across navigation, we use React's cache function to dedupe these function calls and ensure only a single query is made to the db for each request.
42 lines
942 B
TypeScript
42 lines
942 B
TypeScript
import type { Payload, User } from 'payload'
|
|
|
|
import { cache } from 'react'
|
|
|
|
export const getPreference = cache(
|
|
async <T>(key: string, payload: Payload, user: User): Promise<T> => {
|
|
let result: T = null
|
|
|
|
try {
|
|
result = await payload
|
|
.find({
|
|
collection: 'payload-preferences',
|
|
depth: 0,
|
|
limit: 1,
|
|
user,
|
|
where: {
|
|
and: [
|
|
{
|
|
'user.relationTo': {
|
|
equals: payload.config.admin.user,
|
|
},
|
|
},
|
|
{
|
|
'user.value': {
|
|
equals: user.id,
|
|
},
|
|
},
|
|
{
|
|
key: {
|
|
equals: key,
|
|
},
|
|
},
|
|
],
|
|
},
|
|
})
|
|
?.then((res) => res.docs?.[0]?.value as T)
|
|
} catch (_err) {} // eslint-disable-line no-empty
|
|
|
|
return result
|
|
},
|
|
)
|