fix: resolve Google login hydration mismatch and dynamic env load
All checks were successful
Deploy to Production / Build and Deploy (push) Successful in 2m42s
All checks were successful
Deploy to Production / Build and Deploy (push) Successful in 2m42s
This commit is contained in:
@@ -14,6 +14,7 @@ import { useI18n } from '@/lib/i18n';
|
||||
import { apiClient } from '@/lib/apiClient';
|
||||
import { useLogin } from './useLogin';
|
||||
import type { GoogleAuthResponse } from './types';
|
||||
import { useGoogleConfig } from '@/providers/ClientGoogleProvider';
|
||||
|
||||
export function LoginForm() {
|
||||
const [email, setEmail] = useState('');
|
||||
@@ -28,7 +29,7 @@ export function LoginForm() {
|
||||
const searchParams = useSearchParams();
|
||||
const redirect = searchParams.get('redirect') || '/dashboard';
|
||||
|
||||
const googleClientId = process.env.NEXT_PUBLIC_GOOGLE_CLIENT_ID || '';
|
||||
const { clientId: googleClientId, enabled: googleEnabled } = useGoogleConfig();
|
||||
|
||||
useEffect(() => {
|
||||
if (loginMutation.isError && loginMutation.error) {
|
||||
@@ -97,7 +98,7 @@ export function LoginForm() {
|
||||
</CardHeader>
|
||||
|
||||
<CardContent className="space-y-6">
|
||||
{googleClientId && (
|
||||
{googleEnabled && googleClientId && (
|
||||
<>
|
||||
<div className="flex justify-center">
|
||||
{googleLoading ? (
|
||||
|
||||
@@ -27,6 +27,7 @@ import { apiClient } from '@/lib/apiClient';
|
||||
import { useRegister } from './useRegister';
|
||||
import { cn } from '@/lib/utils';
|
||||
import type { GoogleAuthResponse } from '../login/types';
|
||||
import { useGoogleConfig } from '@/providers/ClientGoogleProvider';
|
||||
|
||||
function validateEmail(email: string) {
|
||||
return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
|
||||
@@ -85,7 +86,7 @@ export function RegisterForm() {
|
||||
const searchParams = useSearchParams();
|
||||
const redirect = searchParams.get('redirect') || '/dashboard';
|
||||
|
||||
const googleClientId = process.env.NEXT_PUBLIC_GOOGLE_CLIENT_ID || '';
|
||||
const { clientId: googleClientId, enabled: googleEnabled } = useGoogleConfig();
|
||||
|
||||
const nameError = touched.name && name.length > 0 && name.length < 2
|
||||
? t('register.name.error')
|
||||
@@ -179,7 +180,7 @@ export function RegisterForm() {
|
||||
</CardHeader>
|
||||
|
||||
<CardContent className="space-y-5">
|
||||
{googleClientId && (
|
||||
{googleEnabled && googleClientId && (
|
||||
<>
|
||||
<div className="flex justify-center">
|
||||
{googleLoading ? (
|
||||
|
||||
@@ -6,7 +6,7 @@ import { ThemeProvider } from "@/providers/ThemeProvider";
|
||||
import { NotificationProvider } from "@/components/ui/notification";
|
||||
import { I18nProvider } from "@/lib/i18n";
|
||||
import { Agentation } from "agentation";
|
||||
import { GoogleOAuthProvider } from "@react-oauth/google";
|
||||
import { ClientGoogleProvider } from "@/providers/ClientGoogleProvider";
|
||||
import { CookieConsent } from "@/components/ui/cookie-consent";
|
||||
|
||||
export const dynamic = 'force-dynamic';
|
||||
@@ -37,12 +37,12 @@ export default function RootLayout({
|
||||
<ThemeProvider attribute="class" defaultTheme="system" enableSystem={true} disableTransitionOnChange={false}>
|
||||
<I18nProvider>
|
||||
<QueryProvider>
|
||||
<GoogleOAuthProvider clientId={process.env.NEXT_PUBLIC_GOOGLE_CLIENT_ID || ""}>
|
||||
<ClientGoogleProvider>
|
||||
<NotificationProvider>
|
||||
{children}
|
||||
<CookieConsent />
|
||||
</NotificationProvider>
|
||||
</GoogleOAuthProvider>
|
||||
</ClientGoogleProvider>
|
||||
</QueryProvider>
|
||||
</I18nProvider>
|
||||
{process.env.NODE_ENV === "development" && <Agentation />}
|
||||
|
||||
79
frontend/src/providers/ClientGoogleProvider.tsx
Normal file
79
frontend/src/providers/ClientGoogleProvider.tsx
Normal file
@@ -0,0 +1,79 @@
|
||||
'use client';
|
||||
|
||||
import React, { createContext, useContext, useEffect, useState } from 'react';
|
||||
import { GoogleOAuthProvider } from '@react-oauth/google';
|
||||
import { apiClient } from '@/lib/apiClient';
|
||||
|
||||
interface GoogleConfig {
|
||||
clientId: string;
|
||||
enabled: boolean;
|
||||
loading: boolean;
|
||||
}
|
||||
|
||||
const GoogleConfigContext = createContext<GoogleConfig>({
|
||||
clientId: '',
|
||||
enabled: false,
|
||||
loading: true,
|
||||
});
|
||||
|
||||
export function useGoogleConfig() {
|
||||
return useContext(GoogleConfigContext);
|
||||
}
|
||||
|
||||
export function ClientGoogleProvider({ children }: { children: React.ReactNode }) {
|
||||
const [config, setConfig] = useState<GoogleConfig>({
|
||||
clientId: '',
|
||||
enabled: false,
|
||||
loading: true,
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
let active = true;
|
||||
apiClient
|
||||
.get<{ data: { google_client_id: string; google_auth_enabled: boolean } }>('/api/v1/auth/config')
|
||||
.then((res) => {
|
||||
if (!active) return;
|
||||
setConfig({
|
||||
clientId: res.data.google_client_id,
|
||||
enabled: res.data.google_auth_enabled && !!res.data.google_client_id,
|
||||
loading: false,
|
||||
});
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error('Failed to load Google client configuration:', err);
|
||||
if (!active) return;
|
||||
setConfig({
|
||||
clientId: '',
|
||||
enabled: false,
|
||||
loading: false,
|
||||
});
|
||||
});
|
||||
return () => {
|
||||
active = false;
|
||||
};
|
||||
}, []);
|
||||
|
||||
if (config.loading) {
|
||||
return (
|
||||
<GoogleConfigContext.Provider value={config}>
|
||||
{children}
|
||||
</GoogleConfigContext.Provider>
|
||||
);
|
||||
}
|
||||
|
||||
if (config.enabled && config.clientId) {
|
||||
return (
|
||||
<GoogleConfigContext.Provider value={config}>
|
||||
<GoogleOAuthProvider clientId={config.clientId}>
|
||||
{children}
|
||||
</GoogleOAuthProvider>
|
||||
</GoogleConfigContext.Provider>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<GoogleConfigContext.Provider value={config}>
|
||||
{children}
|
||||
</GoogleConfigContext.Provider>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user