Javascript 材料界面+;从挂钩和x2B起反应;多个复选框+;默认选中

Javascript 材料界面+;从挂钩和x2B起反应;多个复选框+;默认选中,javascript,forms,checkbox,material-ui,react-hook-form,Javascript,Forms,Checkbox,Material Ui,React Hook Form,我正在尝试使用react form hookMaterial UI构建一个包含多个“分组”复选框的表单 复选框是从HTTP请求异步创建的 我想提供一个对象ID数组作为默认值: defaultValues:{boat_id:trip?.boats.map(boat=>boat.id.toString())| |[]} 此外,当我选中或取消选中复选框时,我希望将对象的ID添加/删除到react hook form的值中 即(船号:[25,29,4]) 我怎样才能做到这一点 以下是我试图重现这个问题的

我正在尝试使用
react form hook
Material UI
构建一个包含多个“分组”复选框的表单

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

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

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

此外,当我选中或取消选中复选框时,我希望将对象的ID添加/删除到
react hook form
的值中

即(
船号:[25,29,4]

我怎样才能做到这一点

以下是我试图重现这个问题的一个例子

奖励点,使用Yup验证最小选中复选框


boat\u id:Yup.array().min(2“”)
打破6.X中的API更改:

  • 验证选项已更改为使用解析程序函数包装和其他配置属性名称
    注意:文档只是针对validationResolver->resolver进行了修复,repo中用于验证的代码示例尚未更新(仍然使用
    validationSchema
    进行测试)。感觉好像他们不确定他们想对那里的代码做什么,而且它处于一种不确定的状态。我会完全避免使用他们的控制器,直到它稳定下来,或者使用控制器作为您自己的表单控制器HOC的薄包装,这似乎是他们想要的方向。
    请参见将
    “false”
    值的意外行为作为复选框的字符串,以供参考
  • Controller
    不再以本机方式处理复选框(
    type=“Checkbox”
    ),或者更确切地说,不正确地处理值。它不会检测复选框的布尔值,并尝试将其转换为字符串值。您有几个选择:
  • 不要使用
    控制器
    。使用非受控输入
  • 使用新的
    渲染
    道具为复选框使用自定义渲染功能,并添加一个setValue挂钩
  • 像表单控制器一样使用控制器,并手动控制所有输入
  • 避免使用控制器的示例:


    与第一个原始示例相同,但使用
    yupResolver
    wrapper


    5.X的说明:

    下面是一个不需要控制器的简化示例。非受控是文件中的建议。仍然建议您为每个输入指定自己的
    名称
    ,并对数据进行转换/筛选,以删除未检查的值,如后一示例中的yup和validatorSchema,但出于示例的目的,使用相同的名称会导致将值添加到符合您要求的数组中。

    无论如何,问题是您的
    defaultValues
    与复选框的结构不匹配。它应该是
    {[name]:boolean}
    ,其中生成的
    names
    是文本字符串
    boat_id[${boat.id}]
    ,直到它通过将值聚集到一个数组中的非受控表单输入。例如:
    form\u input1[0]form\u input1[1]
    发出
    form\u input1==[value1,value2]

    生成
    默认值:{“boat_id[0]”:false,“boat_id[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, "")
      });
    

    以下是一个工作版本:

    import React 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 { control, handleSubmit } = useForm({
        defaultValues: {
          bill: "bill",
          luo: ""
        }
      });
    
      return (
        <form onSubmit={handleSubmit(e => console.log(e))}>
          {["bill", "luo"].map(name => (
            <Controller
              key={name}
              name={name}
              as={
                <FormControlLabel
                  control={<Checkbox value={name} />}
                  label={name}
                />
              }
              valueName="checked"
              type="checkbox"
              onChange={([e]) => {
                return e.target.checked ? e.target.value : "";
              }}
              control={control}
            />
          ))}
          <button>Submit</button>
        </form>
      );
    }
    
    从“React”导入React;
    从“react hook form”导入{useForm,Controller};
    从“@material ui/core/FormControlLabel”导入FormControlLabel;
    从“@material ui/core/Checkbox”导入复选框;
    导出默认函数CheckboxesGroup(){
    const{control,handleSubmit}=useForm({
    默认值:{
    比尔:“比尔”,
    罗:""
    }
    });
    返回(
    console.log(e))}>
    {[“比尔”,“罗”].map(名称=>(
    {
    返回e.target.checked?e.target.value:“”;
    }}
    control={control}
    />
    ))}
    提交
    );
    }
    
    代码沙盒链接:


    但是,我不建议这样做,因为material UI中的复选框可能应该返回checked(布尔值)而不是(值)。

    我也一直在努力解决这个问题,以下是对我有效的方法

    react hook form v6的更新解决方案,也可以在不使用
    useState
    的情况下完成(下面的沙盒链接):

    import React,{useState}来自“React”;
    从“react hook form”导入{useForm,Controller};
    从“@material ui/core/FormControlLabel”导入FormControlLabel;
    从“@material ui/core/Checkbox”导入复选框;
    导出默认函数CheckboxesGroup(){
    const defaultNames=[“bill”,“Manos”];
    const{control,handleSubmit}=useForm({
    默认值:{names:defaultNames}
    });
    常量[checkedValues,setCheckedValues]=useState(默认名称);
    函数handleSelect(checkedName){
    const newNames=checkedValues?包括(checkedName)
    ?checkedValues?.filter(名称=>name!==checkedName)
    :[…(checkedValues??[]),checkedName];
    setCheckedValues(新名称);
    返回新名称;
    }
    返回(
    console.log(数据))}>
    {[“比尔”、“罗”、“马诺斯”、“用户120242”].地图(名称=>(
    );
    }}
    control={control}
    />
    }
    键={name}
    label={name}
    />
    ))}
    提交
    );
    }
    
    代码沙盒链接:

    另一个包含默认选定项的解决方案不使用
    useState

    这是我的解决方案,它不是在我的界面上使用Material UI cause中的所有默认组件
      const schema = Yup.object().shape({
        boat_ids: Yup.array()
          .transform(function(o, obj) {
            return Object.keys(obj).filter(k => obj[k]);
          })
          .min(2, "")
      });
    
    import React 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 { control, handleSubmit } = useForm({
        defaultValues: {
          bill: "bill",
          luo: ""
        }
      });
    
      return (
        <form onSubmit={handleSubmit(e => console.log(e))}>
          {["bill", "luo"].map(name => (
            <Controller
              key={name}
              name={name}
              as={
                <FormControlLabel
                  control={<Checkbox value={name} />}
                  label={name}
                />
              }
              valueName="checked"
              type="checkbox"
              onChange={([e]) => {
                return e.target.checked ? e.target.value : "";
              }}
              control={control}
            />
          ))}
          <button>Submit</button>
        </form>
      );
    }