如何在React Hook Form中以布尔值转换输入单选的值



我在React Hook Form中有输入单选,我尝试将其用作真正的布尔值,而不是字符串。

我知道RHF有valueAsNumber将其转换为数字。我认为setValueAs是一种允许任何转换的通用方法,但我无法使其工作。

代码Sanbox


const schema = z.object({
name: z.string().min(4, { message: "4 caractères minimum pour le name" }),
developer: z.boolean() // A real boolean is expected here
});
export default function App() {
const {
register,
handleSubmit,
watch,
formState: { errors }
} = useForm({
resolver: zodResolver(schema),
defaultValues: {
name: "John",
developer: false // default as boolean
}
});
return (
<form onSubmit={handleSubmit(onSubmit)} noValidate>
<input type="text" placeholder="Name" {...register("name")} />
<p>
Is developer ?&nbsp;
<label>
Oui
<input
{...register("developer", {
setValueAs: (val) => true // Try to make it as a real boolean but doesn't work
})}
type="radio"
value={true}
/>
</label>
<label>
Non
<input
{...register("developer", {
setValueAs: (val) => false
})}
type="radio"
value={false}
/>
</label>
</p>
<input type="submit" />
</form>
);
}

知道吗?

我发现了如何从RHF中的无线电输入中获得布尔值。

正如我之前尝试的那样,带有setValueAs的解决方案只适用于文本输入(如type="text"或type="number")。对于单选按钮,即使值是字符串,它也不起作用。

因此,它可以通过使用控制器组件来解决。

代码沙盒

function MyBooleanInput({ control, name }) {
return (
<Controller
control={control}
name={name}
render={({ field: { onChange, onBlur, value, ref } }) => (
<>
<label>
Oui
<input
type="radio"
onBlur={onBlur} // notify when input is touched
onChange={() => onChange(true)} // send value to hook form
checked={value === true}
inputRef={ref}
/>
</label>
<label>
Non
<input
type="radio"
onBlur={onBlur} // notify when input is touched
onChange={() => onChange(false)} // send value to hook form
checked={value === false}
inputRef={ref}
/>
</label>
</>
)}
/>
);
}

通过这种方式,值是真正的布尔值,zod不会抛出错误。

@pom421在我的案例中,setValueAs函数按预期工作。我使用MUI作为UI框架的唯一区别,但不太可能是原因。

我刚刚做了一个助手:

helper.ts

import { RegisterOptions } from 'react-hook-form';
export function forceHtmlRadioOutputToBeBoolean(value: string | null): boolean | null {
if (value === 'true') {
return true;
} else if (value === 'false') {
return false;
} else if (value === null) {
// Sometimes the radio group can be optional, allow this case
return null;
} else {
throw new Error(`this radio group is supposed to only manage string boolean values ("true", "false"), or can optionally be null.`);
}
}
export const reactHookFormBooleanRadioGroupRegisterOptions = {
setValueAs: forceHtmlRadioOutputToBeBoolean,
} as RegisterOptions;

以一种随机的形式,我可以:

<FormControlLabel
value="true"
control={<Radio />}
{...register('alreadyRequestedInThePast', reactHookFormBooleanRadioGroupRegisterOptions)}
label="Yes, I do"
/>

注意,在我的情况下,MUI总是将CCD_;真的";。。。这就是为什么我强迫开发人员在模板方面管理字符串,但之后,他将在React Hook Form(以及zod或其他验证库)中有一个布尔值。

我找到了解决方案。

const { register, handleSubmit, setValue } = useForm<Form>({ defaultValue: ... });
<form onSubmit={handleSubmit(onSubmit)}>
<input
type="radio"
onChange={(e) => setValue('fieldName', getRadioBooleanValue(e))
/>
</form>

如果您不想更改现有结构,但仍然需要布尔值,则可以使用:

setValueAs: (value: string) => (value === 'true' ? true || value === 'false' : false || value),

在CCD_ 7中作为非常微小的快速修复。

最新更新