#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}>
...