在我的代码中没有触发 react-hook-forms 的 onSubmit 函数

react-hook-forms's onSubmit function not getting triggered in my code

为什么我的代码没有触发 onSubmit 函数? (我需要保持原样,或者至少以相同的方式运行,我由 Controller 管理的输入标签需要始终显示状态“价格”,由两个函数更改(handlePriceInputChange , handleSelectedBox)

const schema = yup
  .object({
    voucherPrice: yup.number().positive().required(),
  })
  .required();

function PriceSelection(props) {
  const {
    register,
    handleSubmit,
    control,
    formState: { errors },
  } = useForm({
    resolver: yupResolver(schema),
  });
  const onSubmit = (data) => {
    console.log("does not work?", data);
  };

  const classes = useStylesPriceSelection();
  const [selected, setSelected] = useState(false);
  const [price, setPrice] = useState("");

  const handleSelectedBox = (ev) => {
    console.log("", price);
    setSelected(ev.target.getAttribute("data-boxprice"));
    setPrice(parseInt(ev.target.getAttribute("data-price")));
  };

  const handlePriceInputChange = (ev) => {
    console.log("change", price);
    setPrice(parseInt(ev.target.value));
  };

  const priceBox1 = 25;
  const priceBox2 = 50;
  const priceBox3 = 75;
  const priceBox4 = 100;

  return (
    <div>
      <section className={classes.priceBoxWrap}>
        <div
          data-boxprice="1"
          data-price={`${priceBox1}`}
          onClick={(ev) => handleSelectedBox(ev)}
          className={clsx(
            classes.priceBox,
            ((selected === "1" && price === priceBox1) ||
              price === priceBox1) &&
              classes.priceBoxSelected
          )}
        >
          {`${priceBox1}€`}
        </div>

        <div
          data-boxprice="2"
          data-price={`${priceBox2}`}
          onClick={(ev) => handleSelectedBox(ev)}
          className={clsx(
            classes.priceBox,
            ((selected === "2" && price === priceBox2) ||
              price === priceBox2) &&
              classes.priceBoxSelected
          )}
        >
          {`${priceBox2}€`}
        </div>
      </section>

      <section className={classes.priceBoxWrap}>
        <div
          data-boxprice="3"
          data-price={`${priceBox3}`}
          onClick={(ev) => handleSelectedBox(ev)}
          className={clsx(
            classes.priceBox,
            ((selected === "3" && price === priceBox3) ||
              price === priceBox3) &&
              classes.priceBoxSelected
          )}
        >
          {`${priceBox3}€`}
        </div>

        <div
          data-boxprice="4"
          data-price={`${priceBox4}`}
          onClick={(ev) => handleSelectedBox(ev)}
          className={clsx(
            classes.priceBox,
            ((selected === "4" && price === priceBox4) ||
              price === priceBox4) &&
              classes.priceBoxSelected
          )}
        >
          {`${priceBox4}€`}
        </div>
      </section>
      <form onSubmit={handleSubmit(onSubmit)}>
        <Controller
          name="voucherPrice"
          control={control}
          defaultValue={false}
          rules={{ required: true }}
          render={({ field: { onChange, value, ref, ...field } }) => (
            <Input {...field} onChange={(ev) => handlePriceInputChange(ev)} value={price} type="number" innerRef={ref} />
          )}
        />

        <p>{errors.voucherPrice?.message}</p>

        <Button
          variant="contained"
          sx={{ mt: 1, mr: 1 }}
          type="submit"
        >
          {"Continue"}
        </Button>
      </form>
    </div>
  );
}

export default PriceSelection;

如果 handleSubmit 函数不调用 e.preventDefault 您的页面将刷新,要解决此问题,您可以像这样包装处理程序:

...
const _handleSubmit = (e) => {
    e.preventDefault()
    handleSubmit(e)
}
...
<form onSubmit={_handleSubmit}>
...

对于这种情况,您可以只使用 react-hook-form,并且可以通过 useState 摆脱额外的本地状态管理。我修改了您的示例并删除了 data 属性,并通过 onClick 回调传递了每个盒子的价格值。

const schema = yup
  .object({
    voucherPrice: yup.number().positive().required()
  })
  .required();

const priceBox1 = 25;
const priceBox2 = 50;
const priceBox3 = 75;
const priceBox4 = 100;

const selectedStyles = { outline: "2px solid green" };

function PriceSelection(props) {
  const {
    handleSubmit,
    control,
    formState: { errors },
    setValue,
    watch
  } = useForm({ resolver: yupResolver(schema) });

  const voucherPrice = watch("voucherPrice");

  const onSubmit = (data) => {
    console.log(data);
  };

  const setVoucherPrice = (price) => () => setValue("voucherPrice", price);

  return (
    <div>
      <section>
        <div
          className="pricebox"
          style={voucherPrice === priceBox1 ? selectedStyles : null}
          onClick={setVoucherPrice(priceBox1)}
        >
          {`${priceBox1}€`}
        </div>

        <div
          className="pricebox"
          style={voucherPrice === priceBox2 ? selectedStyles : null}
          onClick={setVoucherPrice(priceBox2)}
        >
          {`${priceBox2}€`}
        </div>
      </section>

      <section>
        <div
          className="pricebox"
          style={voucherPrice === priceBox3 ? selectedStyles : null}
          onClick={setVoucherPrice(priceBox3)}
        >
          {`${priceBox3}€`}
        </div>

        <div
          className="pricebox"
          style={voucherPrice === priceBox4 ? selectedStyles : null}
          onClick={setVoucherPrice(priceBox4)}
        >
          {`${priceBox4}€`}
        </div>
      </section>
      <form onSubmit={handleSubmit(onSubmit)}>
        <Controller
          name="voucherPrice"
          control={control}
          rules={{ required: true }}
          defaultValue={0}
          render={({ field: { ref, ...field } }) => (
            <Input {...field} type="number" innerRef={ref} />
          )}
        />

        <p>{errors.voucherPrice?.message}</p>

        <Button variant="contained" sx={{ mt: 1, mr: 1 }} type="submit">
          {"Continue"}
        </Button>
      </form>
    </div>
  );
}