Skip to content

Commit

Permalink
Fixed reCAPTCHA asynchronous check with React transitions
Browse files Browse the repository at this point in the history
  • Loading branch information
FlorianLeChat committed Dec 14, 2024
1 parent d5ada17 commit 0723728
Show file tree
Hide file tree
Showing 11 changed files with 43 additions and 80 deletions.
12 changes: 3 additions & 9 deletions app/[locale]/authentication/components/oauth.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { useForm } from "react-hook-form";
import serverAction from "@/utilities/recaptcha";
import { useTranslations } from "next-intl";
import { valibotResolver } from "@hookform/resolvers/valibot";
import { useEffect, useActionState, startTransition } from "react";
import { useEffect, useActionState } from "react";

import { Button } from "../../components/ui/button";
import { signInAccount } from "../actions/signin";
Expand Down Expand Up @@ -85,10 +85,7 @@ export default function OAuthForm()
<form
action={( formData ) =>
{
startTransition( () =>
{
serverAction( signInAction, formData, messages );
} );
serverAction( signInAction, formData, messages );
}}
>
<Button
Expand Down Expand Up @@ -123,10 +120,7 @@ export default function OAuthForm()
<form
action={( formData ) =>
{
startTransition( () =>
{
serverAction( signInAction, formData, messages );
} );
serverAction( signInAction, formData, messages );
}}
>
<Button
Expand Down
26 changes: 9 additions & 17 deletions app/[locale]/authentication/components/signin.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ import { useForm } from "react-hook-form";
import serverAction from "@/utilities/recaptcha";
import { useTranslations } from "next-intl";
import { valibotResolver } from "@hookform/resolvers/valibot";
import { useState, useEffect, useActionState } from "react";
import { Eye, Mail, EyeOff, Loader2, KeyRound } from "lucide-react";
import { useState, useEffect, useActionState, startTransition } from "react";

import { Input } from "../../components/ui/input";
import { Form,
Expand All @@ -34,8 +34,8 @@ export default function SignInForm()
{
// Déclaration des variables d'état.
const messages = useTranslations( "form" );
const [ isLocked, setLocked ] = useState( false );
const [ isFocused, setFocused ] = useState( false );
const [ isLocked, setIsLocked ] = useState( false );
const [ isFocused, setIsFocused ] = useState( false );
const [ inputType, setInputType ] = useState( "password" );
const [ signInState, signInAction, isPending ] = useActionState( signInAccount, {
success: true,
Expand Down Expand Up @@ -109,10 +109,7 @@ export default function SignInForm()
}

// Exécution de l'action côté serveur.
startTransition( () =>
{
serverAction( signInAction, formData, messages );
} );
serverAction( signInAction, formData, messages );
}}
className="space-y-6"
>
Expand All @@ -134,9 +131,7 @@ export default function SignInForm()
schema.entries.email.pipe[ 2 ].requirement
}
spellCheck="false"
placeholder={messages(
"fields.email_placeholder"
)}
placeholder={messages( "fields.email_placeholder" )}
autoComplete="email"
autoCapitalize="off"
/>
Expand Down Expand Up @@ -166,21 +161,18 @@ export default function SignInForm()
<Input
{...field}
type={inputType}
onBlur={() => setFocused( field.value?.length > 0 )}
onKeyUp={( event ) => setLocked(
onBlur={() => setIsFocused( field.value?.length > 0 )}
onKeyUp={( event ) => setIsLocked(
event.getModifierState(
"CapsLock"
)
)}
onFocus={() => setFocused( true )}
onFocus={() => setIsFocused( true )}
disabled={isPending}
className={`!mt-0 mr-2 inline-block w-[calc(100%-40px-0.5rem)] transition-opacity ${
!isFocused ? "opacity-50" : ""
}`}
maxLength={
schema.entries.password.options[ 0 ]
.pipe[ 2 ].requirement
}
maxLength={schema.entries.password.options[ 0 ].pipe[ 2 ].requirement}
spellCheck="false"
placeholder={messages(
"fields.password_placeholder"
Expand Down
7 changes: 2 additions & 5 deletions app/[locale]/authentication/components/signup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import serverAction from "@/utilities/recaptcha";
import { Mail, Loader2 } from "lucide-react";
import { useTranslations } from "next-intl";
import { valibotResolver } from "@hookform/resolvers/valibot";
import { useEffect, useActionState, startTransition } from "react";
import { useEffect, useActionState } from "react";

import { Input } from "../../components/ui/input";
import { Button } from "../../components/ui/button";
Expand Down Expand Up @@ -101,10 +101,7 @@ export default function SignUpForm()
}

// Exécution de l'action côté serveur.
startTransition( () =>
{
serverAction( signUpAction, formData, messages );
} );
serverAction( signUpAction, formData, messages );
}}
className="space-y-6"
>
Expand Down
7 changes: 2 additions & 5 deletions app/[locale]/dashboard/components/file-upload.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import { addDays, format } from "date-fns";
import { valibotResolver } from "@hookform/resolvers/valibot";
import { type FileAttributes } from "@/interfaces/File";
import { useLocale, useTranslations } from "next-intl";
import { useEffect, useState, useActionState, startTransition } from "react";
import { useEffect, useState, useActionState } from "react";

import { Label } from "../../components/ui/label";
import { Input } from "../../components/ui/input";
Expand Down Expand Up @@ -377,10 +377,7 @@ export default function FileUpload( {
);

// Exécution de l'action côté serveur.
startTransition( () =>
{
serverAction( uploadAction, formData, formMessages );
} );
serverAction( uploadAction, formData, formMessages );
}}
>
{/* Fichier(s) à téléverser */}
Expand Down
12 changes: 3 additions & 9 deletions app/[locale]/settings/components/appearance.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,9 @@ import { colors } from "@/config/colors";
import { useForm } from "react-hook-form";
import serverAction from "@/utilities/recaptcha";
import type { Session } from "next-auth";
import { useEffect,
useActionState,
startTransition,
type CSSProperties } from "react";
import { useTranslations } from "next-intl";
import { valibotResolver } from "@hookform/resolvers/valibot";
import { useEffect, useActionState, type CSSProperties } from "react";

import { Button } from "../../components/ui/button";
import { Select,
Expand All @@ -46,7 +43,7 @@ import { Form,
import { updateLayout } from "../actions/update-layout";
import { RadioGroup, RadioGroupItem } from "../../components/ui/radio-group";

export default function Appearance( { session }: { session: Session } )
export default function Appearance( { session }: Readonly<{ session: Session }> )
{
// Déclaration des variables d'état.
const messages = useTranslations( "form" );
Expand Down Expand Up @@ -133,10 +130,7 @@ export default function Appearance( { session }: { session: Session } )
formData.append( "theme", form.getValues( "theme" ) );

// Exécution de l'action côté serveur.
startTransition( () =>
{
serverAction( updateAction, formData, messages );
} );
serverAction( updateAction, formData, messages );
}}
className="space-y-8"
>
Expand Down
7 changes: 2 additions & 5 deletions app/[locale]/settings/components/issue.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import { useForm } from "react-hook-form";
import serverAction from "@/utilities/recaptcha";
import { useTranslations } from "next-intl";
import { valibotResolver } from "@hookform/resolvers/valibot";
import { useEffect, useActionState, startTransition } from "react";
import { useEffect, useActionState } from "react";

import { Input } from "../../components/ui/input";
import { Button } from "../../components/ui/button";
Expand Down Expand Up @@ -114,10 +114,7 @@ export default function Account()
}

// Exécution de l'action côté serveur.
startTransition( () =>
{
serverAction( updateAction, formData, messages );
} );
serverAction( updateAction, formData, messages );
}}
className="space-y-8"
>
Expand Down
17 changes: 7 additions & 10 deletions app/[locale]/settings/components/notifications.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import { useForm } from "react-hook-form";
import serverAction from "@/utilities/recaptcha";
import type { Session } from "next-auth";
import { useTranslations } from "next-intl";
import { useState, useEffect, useActionState, startTransition } from "react";
import { useState, useEffect, useActionState } from "react";

import { Switch } from "../../components/ui/switch";
import { Button } from "../../components/ui/button";
Expand All @@ -28,14 +28,14 @@ import { Form,
FormDescription } from "../../components/ui/form";
import { updateNotifications } from "../actions/update-notifications";

export default function Notifications( { session }: { session: Session } )
export default function Notifications( { session }: Readonly<{ session: Session }> )
{
// Déclaration des constantes.
const notifications = session.user.notification.split( "+" );

// Déclaration des variables d'état.
const messages = useTranslations( "form" );
const [ isPush, setPush ] = useState( notifications[ 0 ] !== "off" );
const [ isPush, setIsPush ] = useState( notifications[ 0 ] !== "off" );
const [ updateState, updateAction, isPending ] = useActionState( updateNotifications, {
success: true,
reason: ""
Expand Down Expand Up @@ -108,10 +108,7 @@ export default function Notifications( { session }: { session: Session } )
formData.set( "level", form.getValues( "level" ) );

// Exécution de l'action côté serveur.
startTransition( () =>
{
serverAction( updateAction, formData, messages );
} );
serverAction( updateAction, formData, messages );
}}
className="space-y-8"
>
Expand Down Expand Up @@ -192,7 +189,7 @@ export default function Notifications( { session }: { session: Session } )
checked ? "all" : level
);

setPush( true );
setIsPush( true );
}}
/>
</div>
Expand Down Expand Up @@ -226,7 +223,7 @@ export default function Notifications( { session }: { session: Session } )
checked ? "necessary" : level
);

setPush( true );
setIsPush( true );
}}
/>
</div>
Expand Down Expand Up @@ -261,7 +258,7 @@ export default function Notifications( { session }: { session: Session } )
);
form.setValue( "push", false );

setPush( !checked );
setIsPush( !checked );
}}
/>
</div>
Expand Down
7 changes: 2 additions & 5 deletions app/[locale]/settings/components/privacy.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ import { useForm } from "react-hook-form";
import { redirect } from "next/navigation";
import serverAction from "@/utilities/recaptcha";
import { useTranslations } from "next-intl";
import { useEffect, useActionState } from "react";
import { Files, KeyRound, Scale, Trash, Loader2 } from "lucide-react";
import { useEffect, useActionState, startTransition } from "react";

import { Label } from "../../components/ui/label";
import { Switch } from "../../components/ui/switch";
Expand Down Expand Up @@ -111,10 +111,7 @@ export default function Privacy()
}

// Exécution de l'action côté serveur.
startTransition( () =>
{
serverAction( deleteAction, formData, formMessages );
} );
serverAction( deleteAction, formData, formMessages );
}}
className="space-y-8"
>
Expand Down
9 changes: 3 additions & 6 deletions app/[locale]/settings/components/storage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ import { useForm } from "react-hook-form";
import serverAction from "@/utilities/recaptcha";
import type { Session } from "next-auth";
import { useTranslations } from "next-intl";
import { useEffect, useActionState } from "react";
import { Globe, Link2, RefreshCw, Loader2, History } from "lucide-react";
import { useEffect, useActionState, startTransition } from "react";

import { Label } from "../../components/ui/label";
import { Switch } from "../../components/ui/switch";
Expand All @@ -23,7 +23,7 @@ import { Form,
FormDescription } from "../../components/ui/form";
import { updateStorage } from "../actions/update-storage";

export default function Storage( { session }: { session: Session } )
export default function Storage( { session }: Readonly<{ session: Session }> )
{
// Déclaration des variables d'état.
const messages = useTranslations( "form" );
Expand Down Expand Up @@ -97,10 +97,7 @@ export default function Storage( { session }: { session: Session } )
}

// Exécution de l'action côté serveur.
startTransition( () =>
{
serverAction( updateAction, formData, messages );
} );
serverAction( updateAction, formData, messages );
}}
className="space-y-8"
>
Expand Down
13 changes: 5 additions & 8 deletions app/[locale]/settings/components/user.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import { formatSize } from "@/utilities/react-table";
import type { Session } from "next-auth";
import { valibotResolver } from "@hookform/resolvers/valibot";
import { useLocale, useTranslations } from "next-intl";
import { useState, useEffect, useActionState, startTransition } from "react";
import { useState, useEffect, useActionState } from "react";

import { Input } from "../../components/ui/input";
import { Select,
Expand All @@ -43,11 +43,11 @@ import { Form,
import { updateUser } from "../actions/update-user";
import { Button, buttonVariants } from "../../components/ui/button";

export default function User( { session }: { session: Session } )
export default function User( { session }: Readonly<{ session: Session }> )
{
// Déclaration des variables d'état.
const messages = useTranslations( "form" );
const [ isLocked, setLocked ] = useState( false );
const [ isLocked, setIsLocked ] = useState( false );
const [ updateState, updateAction, isPending ] = useActionState( updateUser, {
success: true,
reason: ""
Expand Down Expand Up @@ -154,10 +154,7 @@ export default function User( { session }: { session: Session } )
}

// Exécution de l'action côté serveur.
startTransition( () =>
{
serverAction( updateAction, formData, messages );
} );
serverAction( updateAction, formData, messages );
}}
className="space-y-8"
>
Expand Down Expand Up @@ -254,7 +251,7 @@ export default function User( { session }: { session: Session } )
<Input
{...field}
type={passwordType}
onKeyUp={( event ) => setLocked(
onKeyUp={( event ) => setIsLocked(
event.getModifierState(
"CapsLock"
)
Expand Down
6 changes: 5 additions & 1 deletion utilities/recaptcha.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
"use client";

import { toast } from "sonner";
import { startTransition } from "react";

export default async function serverAction(
action: ( payload: FormData ) => void,
Expand Down Expand Up @@ -68,7 +69,10 @@ export default async function serverAction(

// On résout enfin l'action côté serveur avec les données du formulaire
// récupérées précédemment.
resolve( await action( formData ) );
startTransition( () =>
{
resolve( action( formData ) );
} );
} );
} );
}

0 comments on commit 0723728

Please sign in to comment.