英文:
A field in a React Hook Form does not update the form state unless that field get the focus
问题
以下是翻译好的部分:
"I am using React Hook Form. I have this simple form:"
我正在使用React Hook Form。我有这个简单的表单:
"When I enter values in the 'quantity' and 'price' fields, the third field, 'total' shows the result of multiplying them. So far, all fine. But I have noticed that when I click the submit button the value in the 'total' field does not update the data form, unless that previously it get the focus by clicking on it."
当我在“数量”和“价格”字段中输入值时,第三个字段“总计”显示它们相乘的结果。到目前为止,一切都很好。但我注意到,当我单击提交按钮时,“总计”字段的值不会更新表单数据,除非之前它获得焦点,需要点击它。
"This is what I get when I don't click the 'total' field:"
这是当我不点击“总计”字段时的情况:
"As you can see in the last image, the value of the 'total' field is not reflected in the form state."
正如您可以在最后一张图中看到的那样,“总计”字段的值没有反映在表单状态中。
"This is my code:"
这是我的代码:
"I was expecting the form state to update regardless of whether or not the 'total' field got focus."
我期望表单状态会更新,无论是否“总计”字段获得焦点。
"Thanks in advance everyone for your help."
非常感谢大家的帮助。
英文:
I am using React Hook Form. I have this simple form:
When I enter values in the "quantity "and "price" fields, the third field, "total" shows the result of multiplying them. So far, all fine. But I have noticed that when I click the submit button the value in the "total" field does not update the data form, unless that previously it get the focus by clicking on it.
This is what I get when I don't click the "total" field:
Showing the state form in the console
As you can see in the last image, the value of the "total" field is not reflected in the form state.
This is my code:
import { useForm } from "react-hook-form"
function App() {
const { register, handleSubmit, watch } = useForm({
defaultValues: {
price: 0,
quantity: 0,
total: 0
}
});
const onSubmit = data => console.log(data)
return (
<div className="App">
<form onSubmit={handleSubmit(onSubmit)}>
<div>
<label htmlFor="quantity">Quantity: </label>
<input type="number"
{...register("quantity")}
/>
</div>
<div>
<label htmlFor="price">Price: </label>
<input type="number"
{...register("price")}
/>
</div>
{
/** 'total' is the result of multiplying the two previous fields.
* It only updates the form data when it get the focus.
*/
}
<div>
<label htmlFor="total">Total: </label>
<input type="number"
{...register("total")}
value={watch('price') * watch('quantity')}
readOnly
/>
</div>
<input type="submit" value='Submit' />
</form>
</div>
)
}
export default App
I was expecting the form state to update regardless of whether or not the "total" field got focus.
Thanks in advance everyone for your help.
答案1
得分: 2
Solved. Thank you @Anurag Srivastava (sorry I'm not allowed to vote yet). This is the final code:
import { useEffect } from "react";
import { useForm } from "react-hook-form";
function App() {
const { register, handleSubmit, setValue, watch } = useForm({
defaultValues: {
price: 0,
quantity: 0,
total: 0
}
});
// I had to add these two lines
const price = watch("price");
const quantity = watch("quantity");
useEffect(() => {
setValue('total', price * quantity);
}, [price, quantity, setValue]);
const onSubmit = data => console.log(data);
return (
<div className="App">
<form onSubmit={handleSubmit(onSubmit)}>
<div>
<label htmlFor="quantity">Quantity: </label>
<input type="number"
{...register("quantity")}
/>
</div>
<div>
<label htmlFor="price">Price: </label>
<input type="number"
{...register("price")}
/>
</div>
{
/** 'total' is the result of multiplying the two previous fields.
* It only updates the form data when it gets the focus.
*/
}
<div>
<label htmlFor="total">Total: </label>
<input type="number"
{...register("total")}
//value={watch('price') * watch('quantity')}
readOnly
/>
</div>
<input type="submit" value='Submit' />
</form>
</div>
)
}
export default App
英文:
Solved. Thank you @Anurag Srivastava (sorry I'm not allowed to vote yet). This is the final code:
import { useEffect } from "react";
import { useForm } from "react-hook-form"
function App() {
const { register, handleSubmit, setValue, watch } = useForm({
defaultValues: {
price: 0,
quantity: 0,
total: 0
}
});
// I had to add these two lines
const price = watch("price")
const quantity = watch("quantity")
useEffect( ()=> {
setValue('total', price * quantity)
}, [price, quantity, setValue])
const onSubmit = data => console.log(data)
return (
<div className="App">
<form onSubmit={handleSubmit(onSubmit)}>
<div>
<label htmlFor="quantity">Quantity: </label>
<input type="number"
{...register("quantity")}
/>
</div>
<div>
<label htmlFor="price">Price: </label>
<input type="number"
{...register("price")}
/>
</div>
{
/** 'total' is the result of multiplying the two previous fields.
* It only updates the form data when it get the focus.
*/
}
<div>
<label htmlFor="total">Total: </label>
<input type="number"
{...register("total")}
//value={watch('price') * watch('quantity')}
readOnly
/>
</div>
<input type="submit" value='Submit' />
</form>
</div>
)
}
export default App
答案2
得分: 1
const price = watch("price")
const quantity = watch("quantity")
使用setValue
结合 useEffect
可能更容易:
const { register, handleSubmit, watch, setValue } = useForm({
defaultValues: { price: 0, quantity: 0, total: 0 }
});
...
useEffect(() => {
setValue('total', quantity * price)
}, [quantity, price])
...
<input type="number"
{...register("total")} // 无需监听
readOnly
/>
英文:
Edit: You would need to watch
the fields as well, to get their values in the app:
const price = watch("price")
const quantity = watch("quantity")
It might be easier for you to use setValue
combined with useEffect
:
const { register, handleSubmit, watch, setValue } = useForm({
defaultValues: { price: 0, quantity: 0, total: 0 }
});
...
useEffect(() => {
setValue('total', quantity * price)
}, [quantity, price])
...
<input type="number"
{...register("total")} // No need to watch
readOnly
/>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论