You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Shadcn Form+Zod中通过onChange获取值并实现密码强度条

解决React Hook Form + Zod表单中密码强度条不更新的问题

核心方案:使用React Hook Form的watch方法

React Hook Form内置的watch API专门用于监听表单字段的实时变化,相比手动调用getValues配合useEffect更可靠,还无需额外维护状态。

修改步骤:

  1. 移除原有的useState和useEffect代码段:
// 删除这部分代码
const [pass, setPass] = useState<string>("");

useEffect(() => {
  setPass(form.getValues("password"));
}, [form]);
  1. 通过watch获取实时密码值:
const password = form.watch("password");
  1. 直接将password传入密码强度组件:
<PasswordStrengthBar password={password} />

完整修改后的代码:

"use client";

import { zodResolver } from "@hookform/resolvers/zod";
import * as z from "zod";
import { useForm } from "react-hook-form";
import { useContext } 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 form = useForm<z.infer<typeof authFormSchema>>({
    resolver: zodResolver(authFormSchema),
    defaultValues: { email: "", password: "" }
  });
  const isLoading = form.formState.isSubmitting;
  // 监听密码字段的实时变化
  const password = form.watch("password");

  async function onSubmit(values: z.infer<typeof authFormSchema>) {
    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;
  }

  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="john@doe.com" {...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={password} />

        <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>
  );
}

备选方案:扩展Input的onChange事件

如果需要手动维护状态,也可以在FormField的渲染逻辑中扩展field.onChange,同时保留React Hook Form的表单逻辑与自定义状态同步:

<FormField
  control={form.control}
  name="password"
  render={({ field }) => (
    <FormItem>
      <FormLabel className="">Password</FormLabel>
      <FormControl>
        <Input 
          placeholder="password123" 
          type="password" 
          {...field} 
          onChange={(e) => {
            // 优先执行原表单的onChange逻辑
            field.onChange(e);
            // 同步更新自定义状态
            setPass(e.target.value);
          }}
        />
      </FormControl>
      <FormMessage />
    </FormItem>
  )}
/>

内容的提问来源于stack exchange,提问作者eyyMinda

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 04:58:13