如何计算total字段并使用hook形式将其设置为数据?

问题描述 投票:0回答:1

您好,我是使用钩子表单的新手,我正在尝试填写一个表单,该表单接受会员类型、价格并根据会员类型计算总价。还将其显示到禁用的总价输入字段中。

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

编辑:我设法通过直接更改属性值而将总价设置到数据对象中,而不将其设置为不同的状态,因为我没有收到任何错误。现在我只是想在改变会员/价格类型时改变总输入的值。

reactjs typescript forms
1个回答
0
投票

我不得不提一下,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;
    }
};
© www.soinside.com 2019 - 2024. All rights reserved.