Material-UI 带有 react-hook-form V7 的复选框在通过逻辑更改检查值时不会发送正确的值

Material-UI checkbox with react-hook-form V7 won't sent correct value when the cheked value is changed via logic

我使用的是 react-hook-form V7.14.2,我使用的是 Material-UI 复选框,可以由用户手动选中或自动选中,具体取决于某些输入的值。 这工作正常。

问题是在提交表单时,如果通过逻辑选中复选框,根据特定输入的值,发送到后端的值将为 false。 如果用户手动选中复选框,那么它将发送正确的值。 -如果选中则为真-.

我在 react-hook-form 页面中阅读了从 V6 迁移到 V7 的文档,因为我之前使用的是 V6 并且代码在那里工作。 https://react-hook-form.com/migrate-v6-to-v7/

我也在 Whosebug 中阅读了一些以前的答案,例如这个:material-ui checkbox with react-hook-form 但没有成功。

这是我的代码:

import React, { useContext, useState, useEffect } from "react";
import Checkbox from "@material-ui/core/Checkbox";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faCheckCircle } from "@fortawesome/free-solid-svg-icons";
import FormControlLabel from "@material-ui/core/FormControlLabel";
import { Controller, set } from "react-hook-form";
import { makeStyles } from "@material-ui/core/styles";
import { DarkThemeContext } from "../../context/DarkThemeContext";
import { useStylesSelectPropDetails } from "../../styledComponent/SelectPropDetailsStyled";
import { IMAGES_LINK } from "../../api/doFetch";

const useStylesLabel = makeStyles((theme) => ({
  label: {
    fontSize: "1em",
    fontFamily: "Open Sans Hebrew, sans-serif !important",
    fontWeight: 400,
    lineHeight: 1.5,
  },
}));

const CheckboxPropDetails = ({
  register,
  name,
  label,
  checked,
  isShelter,
  isElevator,
}) => {
  const classesLabel = useStylesLabel();
  const [isDarkTheme] = useContext(DarkThemeContext);
  const [isChecked, setIsChecked] = useState(false);
  const props = { isDarkTheme: isDarkTheme };
  const classes = useStylesSelectPropDetails(props);

  const handleChange = (event) => {
    setIsChecked(event.target.checked);
  };

  useEffect(() => {
    if (name === "shelter") {
      if (  isShelter,) {
        setIsChecked(true);
      } else setIsChecked(false);
    }
    if (name === "elevator") {
      console.log("elevator");

      if (isElevator) {
        console.log("isElevator", isElevator);
        setIsChecked(true);
      } else setIsChecked(false);
    }
  }, [  isShelter, isElevator]);

  return (
    <>
      <FormControlLabel
        classes={classesLabel}
        control={
          <Checkbox
            name={name}
            id={name}
            defaultChecked={checked ? checked : false}
            {...register(name)}
            color="primary"
            size={"medium"}
            icon={
              <img
                src={`${IMAGES_LINK}/dashboard/elements/rec.svg`}
                alt="Circle"
                style={{ width: 20, height: 20 }}
              />
            }
            disableRipple
            checkedIcon={
              <FontAwesomeIcon
                icon={faCheckCircle}
                style={{ width: 20, height: 20 }}
              />
            }
            checked={isChecked}
            onChange={(e) => handleChange(e)}
          />
        }
        labelPlacement="end"
        label={<p className={classes.paragraphAddProp}>{label}</p>}
      />
    </>
  );
};

在 react-hook-form 上与 V6 一起使用的代码:

import React, { useContext, useState, useEffect } from "react";
import Checkbox from "@material-ui/core/Checkbox";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faCheckCircle } from "@fortawesome/free-solid-svg-icons";
import FormControlLabel from "@material-ui/core/FormControlLabel";
import { Controller } from "react-hook-form";
import { makeStyles } from "@material-ui/core/styles";
import { DarkThemeContext } from "../../context/DarkThemeContext";
import { useStylesSelectPropDetails } from "../../styledComponent/SelectPropDetailsStyled";
import { IMAGES_LINK } from "../../api/doFetch";

const useStylesLabel = makeStyles((theme) => ({
  label: {
    fontSize: "1em",
    fontFamily: "Open Sans Hebrew, sans-serif !important",
    fontWeight: 400,
    lineHeight: 1.5,
  },
}));

const CheckboxPropDetails = ({
  register,
  name,
  label,
  checked,
  isShelter,
  isElevator,
}) => {
  const classesLabel = useStylesLabel();
  const [isDarkTheme] = useContext(DarkThemeContext);
  const props = { isDarkTheme: isDarkTheme };
  const classes = useStylesSelectPropDetails(props);
  const [isChecked, setIsChecked] = useState(false);

  const handleChange = (event) => {
    console.log("event", event.target.checked);
    setIsChecked(event.target.checked);
  };

  useEffect(() => {
    if (name === "shelter") {
      if (isShelter) {
        setIsChecked(true);
      } else setIsChecked(false);
    }
    if (name === "elevator") {   
      if (isElevator) {
           setIsChecked(true);
      } else setIsChecked(false);
    }
  }, [isShelter, isElevator]);

  return (
    <>
      <FormControlLabel
        classes={classesLabel}
        control={
          <Checkbox
            name={name}
            defaultChecked={checked ? checked : false}
            inputRef={register}
            color="primary"
            size={"medium"}
            icon={
              <img
                src={`${IMAGES_LINK}/dashboard/elements/rec.svg`}
                alt="Circle"
                style={{ width: 20, height: 20 }}
              />
            }
            disableRipple
            checkedIcon={
              <FontAwesomeIcon
                icon={faCheckCircle}
                style={{ width: 20, height: 20 }}
              />
            }
            checked={isChecked}
            onChange={(e) => handleChange(e)}
          />
        }
        labelPlacement="end"
        label={<p className={classes.paragraphAddProp}>{label}</p>}
      />
    </>
  );
};

控制、注册等正在作为道具从另一个组件传递。

如前所述,它在 V6 上运行。 V6和V7的区别只有一行:

在 V6 中

  inputRef={register}

在 V7 中

  {...register(name)}

我怎样才能做到这一点,以便当通过逻辑更改选中的值时,它将注册并在提交时将其作为 true 发送到后端?

MUI <Checkbox /> 组件在设置 value 时的界面略有不同。 RHF 值必须使用 checked 属性设置。

在 v6 中,您只是将 register 传递给了 inputRef,但是由于 v7 调用 register 将 return 一个对象 - 这个对象的两个属性是 valueonChange。因此,当将 register 调用扩展到 MUI <Checkbox /> 时,您将实际值的 link 设置为 value 道具,而不是使用 checked 道具.

因此您应该使用 RHF 的 <Controller /> 组件,查看文档 here 以获取有关集成外部受控组件的更多信息。

<FormControlLabel
  control={
    <Controller
      name="checkbox"
      control={control}
      defaultValue={false}
      render={({ field: { value, ref, ...field } }) => (
        <Checkbox
          {...field}
          inputRef={ref}
          checked={!!value}
          color="primary"
          size={"medium"}
          disableRipple
        />
      )}
    />
  }
  label="Checkbox"
  labelPlacement="end"
/>

一个重要提示:您必须使用 checked={!!value} 设置值,以避免在您的 defaultValue for someCheckbox 最初是undefined.