javascript - Finns det ett sätt att få formulärvärden med onChange med Shadcn Form & Zod?
Jag har implementerat ett formulär för att logga in med zod för klient-side validering. Jag ville också lägga till en visning av lösenordets styrka, för vilket jag bestämde mig för att prova react-password-strength-bar.
Funktionaliteten är enkel, du renderar bara PasswordStrengthBar och skickar in lösenordsvärdet som en prop:
import PasswordStrengthBar from "react-password-strength-bar";
<PasswordStrengthBar password={pass} />
När jag försökte göra det har jag märkt att jag inte kan använda onChange-händelselyssnare för inmatningsfältet, eftersom det uppenbarligen redan används. Detsamma gäller för ref, där jag skulle ha använt useEffect som skulle trigga varje gång inmatningsvärdet ändras.
Jag upptäckte att jag kan få värdet med form.getValues("password"), det känns fel att använda formfunktionen som ett beroende som jag sedan skulle använda som ett värde för PasswordStrengthBar. Jag har också försökt placera form i useEffect, men det verkar som om det inte uppdateras med inputändringar.
Har någon några idéer om hur jag skulle kunna få detta att fungera?
Fullständig kod:
"use client";
import { zodResolver } from "@hookform/resolvers/zod";
import * as z from "zod";
import { useForm } from "react-hook-form";
import { useContext, useEffect, useState } from "react";
import NotificationContext from "@/lib/context/notification-context";
import defaultNotification from "@/lib/locale/default-notification";
import PasswordStrengthBar from "react-password-strength-bar";
import { authFormSchema } from "@/lib/formSchema";
import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from "@/components/ui/form";
import { Input } from "@/components/ui/input";
import SubmitButton from "../ui/custom-ui/submit-btn";
export default function AuthForm() {
const notifCtx = useContext(NotificationContext);
const [pass, setPass] = useState<string>("");
const form = useForm<z.infer<typeof authFormSchema>>({
resolver: zodResolver(authFormSchema),
defaultValues: { email: "", password: "" }
});
const isLoading = form.formState.isSubmitting;
async function onSubmit(values: z.infer<typeof authFormSchema>) {
// ✅ This will be type-safe and validated.
notifCtx.setNotification(defaultNotification.pending);
const res = await fetch("/api/auth/signup", {
method: "POST",
body: JSON.stringify({ ...values })
});
const { err, msg } = await res.json();
notifCtx.setNotification(defaultNotification[err ? "error" : "success"](msg));
!err && form.reset();
return;
}
useEffect(() => {
setPass(form.getValues("password"));
}, [form]);
return (
<Form {...form}>
<form onSubmit={form.handleSubmit(onSubmit)} className="space-y-2">
<FormField
control={form.control}
name="email"
render={({ field }) => (
<FormItem>
<FormLabel>Email</FormLabel>
<FormControl>
<Input placeholder="[email " {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="password"
render={({ field }) => (
<FormItem>
<FormLabel className="">Password</FormLabel>
<FormControl>
<Input placeholder="password123" type="password" {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<PasswordStrengthBar password={pass} />
<div className="">
<SubmitButton
className="w-full my-4 dark:bg-white dark:hover:bg-primary dark:text-black dark:hover:text-white"
isLoading={isLoading}
text="Sign up"
/>
</div>
</form>
</Form>
);
}
Svar #1
LÖST: Jag glömde att du kan använda onChangeCapture eftersom det inte innehåller några barnelement för att utlösa fler åtgärder.
<Input placeholder="password123" onChangeCapture={e => setPass(e.currentTarget.value)} type="password" {...field} />
