React Hook Form 设置复选框为选中状态。

12

我正在尝试使用React Hook Form

以下为复选框的简单代码:

import React from 'react'
import { useForm } from 'react-hook-form'

export default function App() {
  const {
    register,
    handleSubmit,
    formState: { errors },
  } = useForm()
  const onSubmit = (data: any) => console.log(data)
  console.log(errors)

  return (
    <div className='mx-auto justify-center p-32 flex'>
      <form onSubmit={handleSubmit(onSubmit)}>
        <div className='p-2'>
          <label htmlFor=''>January</label>
          <input
            type='checkbox'
            placeholder='January'
            {...register('January', {})}
            className='mx-3'
            checked
          />
        </div>
        <div className='p-2'>
          <label htmlFor=''>February</label>
          <input
            type='checkbox'
            placeholder='February'
            {...register('February', {})}
            className='mx-3'
          />
        </div>
        <input type='submit' />
      </form>
    </div>
  )
}

我可以正确提交表单,但我想让一月的复选框作为一个已选中的框开始。然而,当我在代码中加入“checked”后,我似乎无法取消选择它。我可能漏掉了什么,非常感谢任何帮助。

3
乍一看,您只是已经通过了检查并且没有onChange以相应地更改它的状态。 - Leviathan
@Leviathan register() 返回 onChange 和/或 onBlur,所以这不是问题。 - 3limin4t0r
4个回答

19
传递“checked”的问题在于它夺取了“useForm”管理复选框的控制权。
想象一下函数 register() 返回{ checked: true/false, onChange: changeHandler }。因此,如果我们查看生成的属性,会产生以下结果。
<input
  type='checkbox'
  placeholder='January'
  {...register('January', {})}
  className='mx-3'
  checked
/>

<input
  type='checkbox'
  placeholder='January'
  {...{
    checked: true/false,
    onChange: changeHandler,
  }}
  className='mx-3'
  checked
/>

<input
  type='checkbox'
  placeholder='January'
  checked={true/false}
  onChange={changeHandler}
  className='mx-3'
  checked
/>

由于checked出现了两次,后者将覆盖前者。在这种情况下,您的checked是最后一个,因此它会覆盖由useForm管理的值。

register()调用之前传递它也无济于事,因为您的默认值将被useForm管理的值覆盖,因此永远不会使用。


既然我已经解释清楚为什么出现这个问题,让我们继续解决方案。

useForm 允许您在最初调用钩子时传递默认值。

const {
  register,
  handleSubmit,
  formState: { errors },
} = useForm({ defaultValues: { January: true } });

// ...

<input
  type='checkbox'
  {...register("January")}
  className='mx-3'
/>

或者,您可以使用"months"而不是为每个复选框分配自己的名称。如果有多个复选框使用相同的名称,则结果将不是true/false,而是包含值的数组。

const {
  register,
  handleSubmit,
  formState: { errors },
} = useForm({
  defaultValues: { months: ["January"] }
  //               only January ^ is checked by default
});

//...

<input
  type='checkbox'
  value='January'
  {...register("months")}
  className='mx-3'
/>
<input
  type='checkbox'
  value='February'
  {...register("months")}
  className='mx-3'
/>

很好的解释!你知道为什么checkedonChange被返回吗?它不应该是一个不受控制的输入吗?我希望register()只返回引用,这似乎是在库的早期版本中的工作方式 :/. - user3711421
@user3711421 useForm 文档 中提到:*"useForm 是一个自定义的 hook,用于轻松管理表单。"* 这意味着 useForm 将为您管理表单/输入,暗示输入将受到 useForm 的控制。 - 3limin4t0r

4
如果你正在使用React Material UI和React Hook Form,这里有一个最简单的方法让它工作。
import {
  Box
  Checkbox,
  FormControlLabel,
} from '@mui/material'
...
const {
  handleSubmit,
  control,
  formState: { errors },
} = useForm({
})
...

<Box>
<Controller
  control={control}
  name={`${dimension.id}-${dimension.name}`}
  defaultValue={false}
  render={({ field: { onChange, value } }) => (
    <FormControlLabel
      control={
        <Checkbox checked={value} onChange={onChange} />
      }
    />
  )}
/>
</Box>

1
谢谢,这对Mantine复选框也有效! - undefined

3

基于@3limin4tOr的完整工作代码

import React, { useState } from 'react'
import { useForm } from 'react-hook-form'

export default function App() {
  const {
    register,
    handleSubmit,
    formState: { errors },
  } = useForm({
    defaultValues: { months: ['January'] },
  })

  const onSubmit = (data: any) => console.log(data)
  console.log(errors)

  return (
    <div className='mx-auto justify-center p-32 flex'>
      <form onSubmit={handleSubmit(onSubmit)}>
        <div className='p-2'>
          <label htmlFor=''>January</label>
          <input
            type='checkbox'
            value='January'
            placeholder='January'
            {...register('months')}
            className='mx-3'
          />
        </div>
        <div className='p-2'>
          <label htmlFor=''>February</label>
          <input
            type='checkbox'
            value='February'
            placeholder='February'
            {...register('months')}
            className='mx-3'
          />
        </div>
        <input type='submit' />
      </form>
    </div>
  )
}

0

使用React Hook form,您可以在一个字段中找到输入框、复选框和单选框。

import { useState } from "react";
import reactLogo from "./assets/react.svg";
import "./App.css";
import { FormProvider, useForm, useFormContext } from "react-hook-form";

const ChooseCarType = () => {
  const { register } = useFormContext();
  return (
    <>
      <div>
        <label htmlFor="field-rain">
          <input
            {...register("weather")}
            type="radio"
            value="rain"
            id="field-rain"
          />
          Rain
        </label>
        <label htmlFor="field-wind">
          <input
            {...register("weather")}
            type="radio"
            value="wind"
            id="field-wind"
          />
          Lots of wind
        </label>
        <label htmlFor="field-sun">
          <input
            {...register("weather")}
            type="radio"
            value="sun"
            id="field-sun"
          />
          Sunny
        </label>
      </div>
    </>
  );
};

const ChooseService = () => {
  const { register } = useFormContext();
  return (
    <>
      <div>
        <label>
          <input type="checkbox" {...register("jan")} />
          Jan
        </label>
        <label>
          <input type="checkbox" {...register("feb")} />
          Feb
        </label>
        <label>
          <input type="checkbox" {...register("mar")} />
          Mar
        </label>
      </div>
    </>
  );
};

const UserData = () => {
  const { register } = useFormContext();
  return (
    <>
      <div>
        <label>
          Username
          <input {...register("username")} />
        </label>
        <label>
          Password
          <input {...register("password")} />
        </label>
      </div>
    </>
  );
};

function App() {
  const methods = useForm();
  const onSubmit = (data: any) => alert(JSON.stringify(data, null, 2));

  return (
    <FormProvider {...methods}>
      <form onSubmit={methods.handleSubmit(onSubmit)}>
        <ChooseCarType />
        <ChooseService />
        <UserData />
        <button type="submit">Submit</button>
      </form>
    </FormProvider>
  );
}

export default App;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接