From 552df17edb943ff10a34508128f09a3087e3b0a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20K=C3=BCndig?= Date: Fri, 29 Mar 2024 10:31:27 +0100 Subject: [PATCH] website(bugfix): fix client-side rendering issue (#783) --- .../admin/donation-certificates/index.ts | 2 +- .../src/firebase/admin/StorageAdmin.test.ts | 2 +- shared/src/firebase/admin/StorageAdmin.ts | 2 +- website/.gitignore | 1 + .../newsletter-popup-client.tsx | 2 +- .../providers/context-providers.tsx | 23 ++++++++++++++----- 6 files changed, 22 insertions(+), 10 deletions(-) diff --git a/functions/src/webhooks/admin/donation-certificates/index.ts b/functions/src/webhooks/admin/donation-certificates/index.ts index b5e4c2e1f..e2dc32699 100644 --- a/functions/src/webhooks/admin/donation-certificates/index.ts +++ b/functions/src/webhooks/admin/donation-certificates/index.ts @@ -47,7 +47,7 @@ export default onCall>( await withFile(async ({ path }) => { await writer.writeDonationCertificatePDF(path); - const { downloadUrl } = await storageAdmin.uploadAndGetDownloadURL({ + const { downloadUrl } = await storageAdmin.uploadAndGetDownloadUrl({ sourceFilePath: path, destinationFilePath: `users/${userId}/donation-certificates/${writer.year}_${writer.user.language}.pdf`, }); diff --git a/shared/src/firebase/admin/StorageAdmin.test.ts b/shared/src/firebase/admin/StorageAdmin.test.ts index 26cb5c552..17777c212 100644 --- a/shared/src/firebase/admin/StorageAdmin.test.ts +++ b/shared/src/firebase/admin/StorageAdmin.test.ts @@ -19,7 +19,7 @@ describe('useStorageAdmin', () => { test('upload private file', async () => { await fs.writeFile(tmpFile, 'test'); - const { downloadUrl } = await storageAdmin.uploadAndGetDownloadURL({ + const { downloadUrl } = await storageAdmin.uploadAndGetDownloadUrl({ sourceFilePath: tmpFile, destinationFilePath: tmpFile, }); diff --git a/shared/src/firebase/admin/StorageAdmin.ts b/shared/src/firebase/admin/StorageAdmin.ts index ba9a42d49..3c0922c54 100644 --- a/shared/src/firebase/admin/StorageAdmin.ts +++ b/shared/src/firebase/admin/StorageAdmin.ts @@ -33,7 +33,7 @@ export class StorageAdmin { await destinationBucket.upload(sourceFilePath, { destination: destinationFilePath }); }; - uploadAndGetDownloadURL = async ({ bucket, sourceFilePath, destinationFilePath }: UploadProps) => { + uploadAndGetDownloadUrl = async ({ bucket, sourceFilePath, destinationFilePath }: UploadProps) => { const destinationBucket = bucket || this.storage.bucket(); const token = randomBytes(32).toString('hex'); const [file, metadata] = await destinationBucket.upload(sourceFilePath, { diff --git a/website/.gitignore b/website/.gitignore index 8f322f0d8..c2a48cb26 100644 --- a/website/.gitignore +++ b/website/.gitignore @@ -26,6 +26,7 @@ yarn-error.log* # local env files .env*.local +.env.production # vercel .vercel diff --git a/website/src/components/newsletter-popup/newsletter-popup-client.tsx b/website/src/components/newsletter-popup/newsletter-popup-client.tsx index 50a7b33f6..f7499bd9e 100644 --- a/website/src/components/newsletter-popup/newsletter-popup-client.tsx +++ b/website/src/components/newsletter-popup/newsletter-popup-client.tsx @@ -100,7 +100,7 @@ export const NewsletterPopupClient = ({ delay, lang, translations }: NewsletterP return () => { clearTimeout(timeout); }; - }, []); + }, [delay, lang, translations]); return null; }; diff --git a/website/src/components/providers/context-providers.tsx b/website/src/components/providers/context-providers.tsx index a278cb819..65faa072e 100644 --- a/website/src/components/providers/context-providers.tsx +++ b/website/src/components/providers/context-providers.tsx @@ -18,7 +18,7 @@ import { connectFunctionsEmulator, getFunctions } from 'firebase/functions'; import { connectStorageEmulator, getStorage } from 'firebase/storage'; import _ from 'lodash'; import { useRouter, useSearchParams } from 'next/navigation'; -import { PropsWithChildren, createContext, useContext, useEffect, useState } from 'react'; +import { PropsWithChildren, Suspense, createContext, useContext, useEffect, useState } from 'react'; import { AnalyticsProvider, AuthProvider, @@ -150,14 +150,14 @@ type I18nContextType = { const I18nContext = createContext(undefined!); export const useI18n = () => useContext(I18nContext); -function I18nProvider({ children }: PropsWithChildren) { +function I18nUrlUpdater() { + // This component is used to watch the URL and update the language and region in the context if the URL changes. + // It's a separate component because it uses the useSearchParams hook, and needs to be wrapped in a Suspense + // boundary (https://nextjs.org/docs/messages/deopted-into-client-rendering). const router = useRouter(); const searchParams = useSearchParams(); const searchParamsString = searchParams.toString(); - - const { value: language, setCookie: setLanguage } = useCookieState(LANGUAGE_COOKIE); - const { value: region, setCookie: setRegion } = useCookieState(REGION_COOKIE); - const { value: currency, setCookie: setCurrency } = useCookieState(CURRENCY_COOKIE); + const { language, setLanguage, region, setRegion } = useI18n(); useEffect(() => { const urlSegments = window.location.pathname.split('/'); @@ -181,6 +181,14 @@ function I18nProvider({ children }: PropsWithChildren) { } }, [region, router, setRegion]); + return null; +} + +function I18nProvider({ children }: PropsWithChildren) { + const { value: language, setCookie: setLanguage } = useCookieState(LANGUAGE_COOKIE); + const { value: region, setCookie: setRegion } = useCookieState(REGION_COOKIE); + const { value: currency, setCookie: setCurrency } = useCookieState(CURRENCY_COOKIE); + return ( setCurrency(currency, { expires: 365 }), }} > + + + {children} );