функция onSubmit react-hook-forms не запускается в моем коде

#reactjs #react-hooks #react-hook-form #yup

Вопрос:

Почему функция onSubmit не запускается в моем коде? (Мне нужно сохранить все как есть или, по крайней мере, функционировать таким же образом, входной тег, которым я управлял контроллером, должен постоянно отображать состояние «цена», которое изменяется двумя функциями (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" amp;amp; price === priceBox1) ||
              price === priceBox1) amp;amp;
              classes.priceBoxSelected
          )}
        >
          {`${priceBox1}€`}
        </div>

        <div
          data-boxprice="2"
          data-price={`${priceBox2}`}
          onClick={(ev) => handleSelectedBox(ev)}
          className={clsx(
            classes.priceBox,
            ((selected === "2" amp;amp; price === priceBox2) ||
              price === priceBox2) amp;amp;
              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" amp;amp; price === priceBox3) ||
              price === priceBox3) amp;amp;
              classes.priceBoxSelected
          )}
        >
          {`${priceBox3}€`}
        </div>

        <div
          data-boxprice="4"
          data-price={`${priceBox4}`}
          onClick={(ev) => handleSelectedBox(ev)}
          className={clsx(
            classes.priceBox,
            ((selected === "4" amp;amp; price === priceBox4) ||
              price === priceBox4) amp;amp;
              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;

 

Комментарии:

1. была ли ваша функция handleSubmit вызвана e.preventDefault?

2. откуда бы он мог позвонить? Это и есть весь компонент

Ответ №1:

Вы можете просто использовать 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>
  );
}
 

Изменить форму крючка реакции - Базовая (раздвоенная)

Комментарии:

1. проблема в том, что мне нужно, чтобы, если пользователь вводит что-либо на входе, это оценивалось по классам кнопок цены, поэтому они помечаются, если пользователь вводит цену, равную одной из этих кнопок

2. ничего, я выяснил voucherPrice , обновляется в виде строки, теперь все в порядке, большое спасибо

Ответ №2:

Если функция handleSubmit не вызывает e.preventDefault, ваша страница обновится, чтобы исправить это, вы можете обернуть обработчик следующим образом:

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