您好,我是使用钩子表单的新手,我正在尝试填写一个表单,该表单接受会员类型、价格并根据会员类型计算总价。还将其显示到禁用的总价输入字段中。
const AddMember = () => {
const form = useForm<Member>(
{
defaultValues: {
assignedBy: 'admin',
name: '',
lastName: '',
gender: '',
membershipType: '',
startingDate: '',
total: 0
},
resolver: yupResolver(ValidationSchema)
}
);
const { register, control, handleSubmit, formState, watch } = form;
const { isDirty, errors } = formState;
const watchMembershipType = watch('membershipType');
const watchPrice = watch('price');
type Member = {
assignedBy: string
name: string
lastName: string
gender: string
phone: number
membershipType: string
startingDate: string
price: number
total: number
}
let totalPrice: number;
const calculatePrice = (data: Member) => {
switch (watchMembershipType) {
case '1 month':
data.total = watchPrice;
totalPrice = watchPrice;
break;
case '3 months':
data.total = (watchPrice * 3) - (watchPrice * 3) * 0.1;
totalPrice = (watchPrice * 3) - (watchPrice * 3) * 0.1;
break;
case '1 year':
data.total = (watchPrice * 12) - (watchPrice * 12) * 0.2;
totalPrice = (watchPrice * 12) - (watchPrice * 12) * 0.2;
break;
}
}
const onSubmit = (data: Member) => {
calculatePrice(data);
console.log(totalPrice);
console.log(data);
}
return (
<div className='add-member'>
{/*..previos code of the form..*/}
<div className='input' id='price-input'>
<label>Price </label>
<input {...register('price')} placeholder='$ (per month)' className={errors.price?.message ? 'error' : ''} />
</div>
<div className='input' id='price-total'>
<label>Total</label>
{/* <input value={`${totalPrice}`} {...register('total')} disabled={true} /> */}
</div>
<button type='submit' disabled={!isDirty}>Submit</button>
</div>
</form>
<DevTool control={control} />
</div>
)
}
export default AddMember
编辑:我设法通过直接更改属性值而将总价设置到数据对象中,而不将其设置为不同的状态,因为我没有收到任何错误。现在我只是想在改变会员/价格类型时改变总输入的值。
我不得不提一下,React 并不是以这种方式工作的——重新分配变量不会触发组件的重新渲染。在函数calculatePrice中,对变量totalPrice进行了重新赋值,但它不会触发重新渲染,因此您在页面上看不到任何变化。 React 有很多方法可以做到这一点,我将展示非常简单的方法:
const calculatePrice = (data: Member) => {
let totalPrice: number;
switch (watchMembershipType) {
case "1 month":
data.total = watchPrice;
totalPrice = watchPrice;
setCalculatedTotal(totalPrice);
break;
case "3 months":
data.total = watchPrice * 3 - watchPrice * 3 * 0.1;
totalPrice = watchPrice * 3 - watchPrice * 3 * 0.1;
setCalculatedTotal(totalPrice);
break;
case "1 year":
data.total = watchPrice * 12 - watchPrice * 12 * 0.2;
totalPrice = watchPrice * 12 - watchPrice * 12 * 0.2;
setCalculatedTotal(totalPrice);
break;
}
};
我添加了一个带有 useState 挂钩的状态变量。当用户填写表单并点击“提交”时,函数calculateTotal 会计算总计并在state 中设置该值。这会触发组件的重新渲染并显示值。
另一种方法是使用 useForm 钩子的状态:
const calculatePrice = (data: Member) => {
let totalPrice: number;
switch (watchMembershipType) {
case "1 month":
data.total = watchPrice;
totalPrice = watchPrice;
setValue("total", totalPrice);
break;
case "3 months":
data.total = watchPrice * 3 - watchPrice * 3 * 0.1;
totalPrice = watchPrice * 3 - watchPrice * 3 * 0.1;
setValue("total", totalPrice);
break;
case "1 year":
data.total = watchPrice * 12 - watchPrice * 12 * 0.2;
totalPrice = watchPrice * 12 - watchPrice * 12 * 0.2;
setValue("total", totalPrice);
break;
}
};