Reputation: 621
I am having an error when submiting a form build using React Hook Form and material-ui checkboxes components. The number of checkboxes are build from a list from my api:
<Grid item xs={12}>
<FormControl
required
error={errors.project?.stack ? true : false}
component='fieldset'>
<FormLabel component='legend'>Tech Stack</FormLabel>
<FormGroup>
<Grid container spacing={1}>
{techs.map((option, i) => (
<Grid item xs={4} key={i}>
<FormControlLabel
control={
<Checkbox
id={`stack${i}`}
name='project.stack'
value={option.id}
inputRef={register({required: 'Select project Tech Stack'})}
/>
}
label={option.name}
/>
</Grid>
))}
</Grid>
</FormGroup>
<FormHelperText>{errors.project?.stack}</FormHelperText>
</FormControl>
</Grid>
When the form is submited I got the following error ( several times , 1 for each checkbox rendered ) :
Uncaught (in promise) Error: Objects are not valid as a React child (found: object with keys {type, message, ref}). If you meant to render a collection of children, use an array instead.
I don't understand this error. The message apparently says it is a rendering issue, but the component renders fine. The problems happens on submit. Any advices ?
Thank you
Upvotes: 28
Views: 59338
Reputation: 8418
Here is the simplest way to do it using Controller
<Box>
<Controller
control={control}
name={`${dimension.id}-${dimension.name}`}
defaultValue={false}
render={({ field: { onChange, value } }) => (
<FormControlLabel
control={
<Checkbox checked={value} onChange={onChange} />
}
/>
)}
/>
</Box>
Upvotes: 3
Reputation: 1898
UPDATE: if you are using RHF >= 7, you should use props.field
to call props.field.value
and props.field.onChange
.
You can use the default Checkbox Controller:
<FormControlLabel
control={
<Controller
name={name}
control={control}
render={({ field: props }) => (
<Checkbox
{...props}
checked={props.value}
onChange={(e) => props.onChange(e.target.checked)}
/>
)}
/>
}
label={label}
/>
I used the controller example from RHF but had to add checked={props.value}
:
https://github.com/react-hook-form/react-hook-form/blob/master/app/src/controller.tsx
Upvotes: 40
Reputation: 41
Material UI + React Hook Form + Yup . Example page: https://moiseshp.github.io/landing-forms/
// import { yupResolver } from '@hookform/resolvers/yup'
// import * as yup from 'yup'
const allTopics = [
'React JS',
'Vue JS',
'Angular'
]
const defaultValues = {
topics: []
}
const validationScheme = yup.object({
topics: yup.array().min(1),
})
const MyForm = () => {
const resolver = yupResolver(validationScheme)
const {
control,
formState: { errors },
handleSubmit
} = useForm({
mode: 'onChange',
defaultValues,
resolver
})
const customSubmit = (data) => alert(JSON.stringify(data))
return (
<form onSubmit={handleSubmit(customSubmit)}>
<FormControl component="fieldset" error={!!errors?.topics}>
<FormLabel component="legend">Topics</FormLabel>
<FormGroup row>
<Controller
name="topics"
control={control}
render={({ field }) => (
allTopics.map(item => (
<FormControlLabel
{...field}
key={item}
label={item}
control={(
<Checkbox
onChange={() => {
if (!field.value.includes(item)) {
field.onChange([...field.value, item])
return
}
const newTopics = field.value.filter(topic => topic !== item)
field.onChange(newTopics)
}}
/>
)}
/>
))
)}
/>
</FormGroup>
<FormHelperText>{errors?.topics?.message}</FormHelperText>
</FormControl>
</form>
)
}
export default MyForm
Upvotes: 1
Reputation: 6685
If someone struggle to achieve multiselect checkbox with React material-ui and react-hook-form you can check my codesandbox example
Also, there is a code example provided by react-hook-form in their documentation under useController
chapter (don't forget to switch to the checkboxes tab).
Upvotes: 10
Reputation: 67
Any of that examples works, I´m using this one:
const checboxArray = [{
name: '1h',
label: '1 hora'
},
{
name: '12h',
label: '12 horas'
},
{
name: '24h',
label: '24 horas'
},
{
name: '3d',
label: '3 dias'
},
];
//This inside render function:
{
checboxArray.map((checboxItem) => (
<Controller name = {
checboxItem.name
}
control = {
control
}
key = {
checboxItem.name
}
rules = {
{
required: true
}
}
render = {
({
field: {
onChange,
value
}
}) =>
<
FormControlLabel
control = { <Checkbox
checked = {!!value
}
onChange = {
(event, item) => {
onChange(item);
}
}
name = {
checboxItem.name
}
color = "primary" /
>
}
label = {
checboxItem.label
}
/>
}
/>
))
}
Upvotes: 1
Reputation: 621
I managed to make it work without using Controller. The props should be inside the FormControlLabel and not inside Checkbox
<Grid item xs={4} key={i}>
<FormControlLabel
value={option.id}
control={<Checkbox />}
label={option.name}
name={`techStack[${option.id}]`}
inputRef={register}
/>
</Grid>
))}
Upvotes: 11