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

如何用URL参数设置单选按钮默认值(Next.js + react-hook-form)

解决Next.js + React Hook Form单选按钮默认选中不生效问题

问题根源

Next.js客户端组件首次渲染时,router.query会是undefined或空对象——路由参数需要异步加载。你用defaultChecked设置初始选中状态,但这个属性仅在组件首次渲染时生效,后续路由参数更新后不会自动同步。另外,React Hook Form会接管表单状态,defaultChecked和受控表单状态容易产生冲突。

解决方案

  1. 监听router.query的变化,用React Hook Form的setValue同步表单值
  2. 将单选按钮改为受控组件,由React Hook Form管理选中状态,移除defaultChecked
  3. 过滤无效的accountType参数,仅在参数为buyer/seller时设置表单值

修改后的代码

Fields.jsx

import { forwardRef } from 'react'

function Label({ id, children }) {
  return (
    <label htmlFor={id}>
      {children}
    </label>
  )
}

export const RadioFieldWithRef = forwardRef(function RadioField({ id, label, options, name, className = '', ...props }, ref) {
  return (
    <div className={className}>
      {label && <Label id={id}>{label}</Label>}
      <div>
        {options.map((option) => {
          // 通过表单值判断当前选项是否被选中
          const isChecked = props.value === option.value;
          return (
            <div className="flex items-center" key={option.value}>
              <input
                id={option.value}
                name={name}
                type="radio"
                value={option.value}
                checked={isChecked}
                ref={ref}
                {...props}
              />
              <label htmlFor={option.value}>
                {option.label}
              </label>
            </div>
          )
        })}
      </div>
    </div>
  )
})

signup.jsx

import { useRouter } from 'next/router'
import { useEffect } from 'react'
import { RadioFieldWithRef } from '@/components/Fields'
import { useForm } from "react-hook-form";

export default function Signup() {
  const router = useRouter()
  const { accountType } = router.query
  
  const { register, setValue, formState: { errors } } = useForm();
  const accountTypeField = register("account_type", {
    required: "Must select account type"
  })

  // 监听accountType变化,同步表单值
  useEffect(() => {
    if (accountType && ['buyer', 'seller'].includes(accountType)) {
      setValue('account_type', accountType);
    }
  }, [accountType, setValue])

  return (
    <form>
      <RadioFieldWithRef
        label="I'm a ..."
        name="account_type"
        options={ [
          { label: 'Buyer', value: 'buyer' },
          { label: 'Seller', value: 'seller' },
        ] }
        {...accountTypeField}
      />
      {errors.account_type && <p className="text-red-500">{errors.account_type.message}</p>}
      <button type="submit">Submit</button>
    </form>
  )
}

关键说明

  • 用useEffect监听accountType的变化,确保路由参数加载完成后再设置表单值
  • 将单选按钮改为受控组件,通过props.value判断选中状态,完全由React Hook Form管理表单状态
  • 增加无效参数过滤,避免非法值设置到表单中
  • 保留表单校验逻辑,确保用户必须选择一个身份

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 22:45:58