Material UI React Form Hook 多个复选框默认选中

新手上路,请多包涵

我正在尝试使用 react-form-hook Material UI 构建一个可容纳多个“分组”复选框的表单。

复选框是从 HTTP 请求异步创建的。

我想提供一组对象 ID 作为默认值:

defaultValues: { boat_ids: trip?.boats.map(boat => boat.id.toString()) || [] }

此外,当我选择或取消选择一个复选框时,我想将 对象的 ID 添加/删除到 react-hook-form 的值。

IE。 ( boat_ids: [25, 29, 4]

我怎样才能做到这一点?

这是我试图重现该问题的 示例

加分,使用 Yup 验证最小选中复选框

boat_ids: Yup.array() .min(2, "")

原文由 Manos 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 470
2 个回答

6.X 中的重大 API 更改:

  • 验证选项已更改为使用解析器函数包装器和不同的配置属性名称

注意:文档只是针对 validationResolver->resolver 进行了修复,并且 repo 中用于验证的代码示例尚未更新(仍然使用 validationSchema 进行测试)。感觉好像他们不确定他们想用那里的代码做什么,而且它处于一种不确定的状态。我会完全避免使用他们的 Controller,直到它稳定下来,或者将 Controller 用作您自己的表单 Controller HOC 的薄包装,这似乎是他们想要进入的方向。

查看 官方沙箱演示 和意外行为 "false" 值作为复选框的字符串以供参考

import { yupResolver } from "@hookform/resolvers";

   const { register, handleSubmit, control, getValues, setValue } = useForm({
    resolver: yupResolver(schema),
    defaultValues: Object.fromEntries(
      boats.map((boat, i) => [
        `boat_ids[${i}]`,
        preselectedBoats.some(p => p.id === boats[i].id)
      ])
    )
  });

  • Controller 不再本地处理复选框( type="checkbox" ),或者更准确地说,错误地处理值。它不检测复选框的布尔值,并尝试将其转换为字符串值。你有几个选择:
  1. 不要使用 Controller 。使用不受控制的输入
  2. 使用新的 render 道具为您的复选框使用自定义渲染功能并添加一个 setValue 挂钩
  3. 像表单控制器 HOC 一样使用 Controller 并手动控制所有输入

避免使用 Controller 的示例:

https://codesandbox.io/s/optimistic-paper-h39lq

https://codesandbox.io/s/silent-mountain-wdiov

与第一个原始示例相同,但使用 yupResolver 包装器


5.X 的说明:

这是一个不需要 Controller 的简化示例。不受控制是文档中的建议。仍然建议您为每个输入提供自己的 name 并对数据进行转换/过滤以删除未检查的值,例如在后一个示例中使用 yup 和 validatorSchema,但为了示例的目的,使用相同的名称会导致将值添加到符合您要求的数组中。

https://codesandbox.io/s/practical-dijkstra-f1yox

无论如何,问题是您的 defaultValues 与复选框的结构不匹配。它应该是 {[name]: boolean} ,其中 names 生成的是 文字字符串 boat_ids[${boat.id}] ,直到它通过一个不受控制的值形式输入数组。例如: form_input1[0] form_input1[1] 发出 form_input1 == [value1, value2]

https://codesandbox.io/s/determined-paper-qb0lf

构建 defaultValues: { "boat_ids[0]": false, "boat_ids[1]": true ... }

控制器需要布尔值来切换复选框值,并将其作为默认值提供给复选框。

  const { register, handleSubmit, control, getValues, setValue } = useForm({
    validationSchema: schema,
    defaultValues: Object.fromEntries(
      preselectedBoats.map(boat => [`boat_ids[${boat.id}]`, true])
    )
  });

用于 validationSchema 的模式,验证至少选择了 2 个,并在将数据发送到 onSubmit 之前将数据转换为所需的模式。它过滤掉错误的值,所以你得到一个字符串 id 数组:

   const schema = Yup.object().shape({
    boat_ids: Yup.array()
      .transform(function(o, obj) {
        return Object.keys(obj).filter(k => obj[k]);
      })
      .min(2, "")
  });

原文由 user120242 发布,翻译遵循 CC BY-SA 4.0 许可协议

我也一直在为此苦苦挣扎,这对我有用。

更新了 react-hook-form v6 的解决方案,它也可以在没有 useState 的情况下完成(下面的沙盒链接):

 import React, { useState } from "react";
import { useForm, Controller } from "react-hook-form";
import FormControlLabel from "@material-ui/core/FormControlLabel";
import Checkbox from "@material-ui/core/Checkbox";

export default function CheckboxesGroup() {
  const defaultNames = ["bill", "Manos"];
  const { control, handleSubmit } = useForm({
    defaultValues: { names: defaultNames }
  });

  const [checkedValues, setCheckedValues] = useState(defaultNames);

  function handleSelect(checkedName) {
    const newNames = checkedValues?.includes(checkedName)
      ? checkedValues?.filter(name => name !== checkedName)
      : [...(checkedValues ?? []), checkedName];
    setCheckedValues(newNames);

    return newNames;
  }

  return (
    <form onSubmit={handleSubmit(data => console.log(data))}>
      {["bill", "luo", "Manos", "user120242"].map(name => (
        <FormControlLabel
          control={
            <Controller
              name="names"
              render={({ onChange: onCheckChange }) => {
                return (
                  <Checkbox
                    checked={checkedValues.includes(name)}
                    onChange={() => onCheckChange(handleSelect(name))}
                  />
                );
              }}
              control={control}
            />
          }
          key={name}
          label={name}
        />
      ))}
      <button>Submit</button>
    </form>
  );
}

代码沙盒链接: https ://codesandbox.io/s/material-demo-54nvi?file=/demo.js

另一种默认选择项目的解决方案没有 useStatehttps ://codesandbox.io/s/material-demo-bzj4i?file=/demo.js

原文由 Arthur Burgan 发布,翻译遵循 CC BY-SA 4.0 许可协议

推荐问题