Gotey
Gotey

Reputation: 629

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

Why the function onSubmit does not get triggered in my code? (I need to keep it all as it is, or ar least to function in the same manner, the Input tag I have managed by Controller, needs to show a state "price" all the time, which is changed by two functions (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;

Upvotes: 0

Views: 2089

Answers (2)

knoefel
knoefel

Reputation: 6949

You can just use react-hook-form for this situation and can get rid of the additional local state management via useState. I reworked your example and removed the data attributes and just passed the price values for each box via the onClick callback.

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>
  );
}

Edit React Hook Form - Basic (forked)

Upvotes: 1

Plargato
Plargato

Reputation: 555

If the handleSubmit function does not call e.preventDefault your page will refresh, to fix this you can wrap the handler like this:

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

Upvotes: 1

Related Questions