React Hook 表单 + Material UI 复选框

React Hook Forms + Material UI Checkboxes

我在使用 React Hook 表单和 material-ui 复选框组件提交表单 build 时遇到错误。复选框的数量是 build 来自我的列表 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>

提交表单时出现以下错误(几次,每个复选框呈现 1 个):

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.

我不明白这个错误。该消息显然表明这是一个呈现问题,但组件呈现正常。问题发生在提交上。有什么建议吗?

谢谢

我设法在不使用 Controller 的情况下使其工作。 道具应该在 FormControlLabel 内而不是在 Checkbox

                <Grid item xs={4} key={i}>
                    <FormControlLabel
                      value={option.id}
                      control={<Checkbox />}
                      label={option.name}
                      name={`techStack[${option.id}]`}
                      inputRef={register}
                    />
                  </Grid>
                ))}

UPDATE: 如果你使用 RHF >= 7,你应该使用 props.field 调用 props.field.valueprops.field.onChange.


您可以使用默认的复选框控制器:

<FormControlLabel
    control={
      <Controller
        name={name}
        control={control}
        render={(props) => (
          <Checkbox
            {...props}
            checked={props.value}
            onChange={(e) => props.onChange(e.target.checked)}
          />
        )}
      />
    }
    label={label}
  />

我使用了 RHF 的控制器示例,但必须添加 checked={props.value}https://github.com/react-hook-form/react-hook-form/blob/master/app/src/controller.tsx

任何一个例子都有效,我正在使用这个:

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
      }
      />
    }
    />
  ))
}

如果有人难以通过 React material-ui 和 react-hook-form 实现多选复选框,您可以查看我的 codesandbox example

另外,react-hook-form 在其文档 useController 章节下提供了 code example(不要忘记切换到复选框选项卡)。

Material UI + React Hook Form + 是的 。 示例页面: 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