Issue
I am trying out React-Hook-form
The simple code for the checkbox is as below:
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>
)
}
I can submit the form correctly but I have like the January checkbox to start off as a checked box but when I put 'checked' as shown in the code, I somehow could not 'uncheck' it.
I seem to be missing something and any help would be greatly appreciated.
Solution
The issue with passing checked
is that it takes control away from useForm
to manage the checkbox. useForm
register()
uses change handlers (onChange
/onBlur
) to update the checked
(or value
for non-checkboxes) attributes of the actual DOM <input>
element.
By passing the checked
prop you are overriding the checked
DOM attribute that is managed by useForm
. This causes the checkbox to be unable to change state.
Now that I've cleared up why this issue happens let's move on to the solution. This can be solved in two ways:
useForm
allows you to pass a default values when you initially call the hook.const { register, handleSubmit, formState: { errors }, } = useForm({ defaultValues: { January: true } }); // ... <input type="checkbox" {...register("January")} />
Or use the
defaultChecked
property of an<input type="checkbox" />
this holds the initial checked value and doesn't override the current value likechecked
does.const { register, handleSubmit, formState: { errors }, } = useForm(); // ... <input type="checkbox" {...register("January")} defaultChecked />
Note that it's not a good idea to combine the two methods. Use one or the other. The useForm
says the following in the defaultValues
section:
The
defaultValues
prop populates the entire form with default values. It supports both synchronous and asynchronous assignment of default values. While you can set an input's default value usingdefaultValue
ordefaultChecked
(as detailed in the official React documentation), it is recommended to usedefaultValues
for the entire form.
In the given scenario it's probably better to use an array of selected values ["January", "March"]
instead of an object { January: true, February: false, March: true }
.
You can get the array result by using an (empty) array as the default value, and registering the checkboxes under the same name. If any values are present inside the array, they will be checked by default. The values used in the array will match the checkbox value
property.
const {
register,
handleSubmit,
formState: { errors },
} = useForm({
defaultValues: { months: ["January"] }
// mark months as array and ^ check the checkbox with value "January"
});
// ...
// add the a `value` prop to the checkboxes
<input
type="checkbox"
value="January"
{...register("months")}
/>
<input
type="checkbox"
value="February"
{...register("months")}
/>
Answered By - 3limin4t0r
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.