解决react-hook-form中自定义组件onChange事件不触发问题
问题描述
我有一个结算购物车页面,其中包含不同的购物项,用户可在购买前修改每个商品的数量。表单提交功能正常,提交后能获取输入框的值数组,但自定义组件的onChange事件不再触发,如何让该事件正常触发,以便在<Checkout />组件中打印输入框的值?
代码示例
Checkout组件代码
import React, { useEffect, useState } from "react"; import PureInput from "./PureInput"; import { useForm, Controller } from "react-hook-form"; const CartInner = React.forwardRef( ( { control, element, value, handleOnChange, images, name, monthlyAmount, price, projectedGrowth, id, ...inputProps }: any, ref: any ) => { return ( <div className="grid gap-8 grid-cols-2 mb-12 py-6 px-8 border-2 border-slate-200"> <div> <PureInput min={200} max={price} onChange={handleOnChange} type="number" step={200} defaultValue={element.price} id={id} ref={ref} {...inputProps} /> </div> </div> ); } ); export default function Checkout() { const { control, handleSubmit } = useForm(); const handleOnChange = (index: any, e: any) => { console.log(e, "e"); }; const onSubmit = async (data: any) => { console.log(data, "data from Form.tsx"); }; return ( <form onSubmit={handleSubmit(onSubmit)} className="grid gap-8 grid-cols-3"> <div className="col-span-2"> {[0, 2].map((element, index) => { return ( <fieldset key={index}> <Controller render={({ field }) => ( <CartInner element={element} handleOnChange={(e) => handleOnChange(index, e)} {...field} /> )} name={`test.${index}.lastName`} control={control} /> </fieldset> ); })} <button>Progess to payment</button> </div> </form> ); }
PureInput组件代码
import * as React from "react"; type IProps = any; const PureInput = React.forwardRef( ({ className, id, onChange, ...inputProps }: IProps, ref: any) => { return ( <input id={id} ref={ref} onChange={onChange} type="input" className={`${className} block w-full bg-white text-black rounded-md border-2 font-bold border-grey-200 text-xl px-4 py-4 focus:border-orange-500 focus:ring-orange-500`} {...inputProps} /> ); } ); export default PureInput;
提交后的数据示例
[{"lastName": "1600"}, {"lastName": "800"}]
依赖版本
"react-dom": "18.2.0", "react-hook-form": "^7.29.0"
解决方案
问题出在CartInner组件的事件绑定逻辑和属性传递顺序上:
- 属性覆盖问题:传递给
PureInput的onChange={handleOnChange}被后续的{...inputProps}覆盖——inputProps包含了react-hook-form的field.onChange,导致自定义事件无法触发。 - 事件未合并:自定义
handleOnChange和表单状态更新事件需要同时执行,才能兼顾打印日志和表单数据更新。
修改步骤
- 修改CartInner组件,合并事件处理逻辑
const CartInner = React.forwardRef( ( { control, element, value, handleOnChange, images, name, monthlyAmount, price, projectedGrowth, id, ...inputProps }: any, ref: any ) => { // 合并自定义事件与表单更新事件 const combinedOnChange = (e: any) => { handleOnChange(e); // 触发react-hook-form的onChange以维护表单状态 inputProps.onChange?.(e); }; return ( <div className="grid gap-8 grid-cols-2 mb-12 py-6 px-8 border-2 border-slate-200"> <div> <PureInput min={200} max={price} onChange={combinedOnChange} // 使用合并后的事件 type="number" step={200} defaultValue={element.price} id={id} ref={ref} {...inputProps} /> </div> </div> ); } );
- 修正PureInput组件的type属性
原代码中type="input"是错误的,改为type="number"以匹配数字输入需求:
<input id={id} ref={ref} onChange={onChange} type="number" // 修正为数字类型 className={`${className} block w-full bg-white text-black rounded-md border-2 font-bold border-grey-200 text-xl px-4 py-4 focus:border-orange-500 focus:ring-orange-500`} {...inputProps} />
修改完成后,自定义的handleOnChange会正常触发打印输入框值,同时表单提交功能不受影响。
内容的提问来源于stack exchange,提问作者a7dc
相关产品推荐
相关产品推荐

