最新版本的react-hook-form和rc-input-number是9.3.0版本时出现Illegal invocation错误
"react": "18.3.1", "react-dom": "18.3.1", "rc-input-number": "^9.3.0", "@hookform/resolvers": "^3.9.1", "react-hook-form": "^7.54.1",
用以上版本时, 如下代码 import { Box, Form } from 'grommet'; import { z } from 'zod'; import { SubmitHandler, useForm } from 'react-hook-form'; import { zodResolver } from '@hookform/resolvers/zod'; import InputNumber from 'rc-input-number';
const zodFormSchema = z.object({ orderQty: z.coerce.number().positive('必须正数'), });
type ZodFormFieldsProps = z.infer<typeof zodFormSchema>; /**
- 测试inputNumber组件
- */ export default function TestInputNumber() { const { register, handleSubmit, setValue } = useForm<ZodFormFieldsProps>({ resolver: zodResolver(zodFormSchema), });
const onOrderQtyChange = (val: string | number | null) => { setValue('orderQty', val ? parseFloat(val + '') : 0, { shouldValidate: true, shouldTouch: true, shouldDirty: true, }); }; const onFormSubmit: SubmitHandler<ZodFormFieldsProps> = (formData) => { console.log('formData', formData); };
return ( <Box> <Form onSubmit={handleSubmit(onFormSubmit)}> <InputNumber {...register('orderQty')} min={0} step={1} onChange={onOrderQtyChange} /> </Form> </Box> ); }
会报 hook.js:608 React Router caught the following error during render TypeError: Illegal invocation at Proxy.set (react-dom.development.js:1661:1)错误 但是如果将"rc-input-number": "^9.0.0",改为此版本,上面其他内容都不变,则不会报错,使用正常
My workaround is to use Controller instead of register
❌
<NumberInput {...register('price')} />
✅
<Controller render={({field: {value, onChange}}) => (
<NumberInput value={value} onChange={onChange}/>
)}/>
I recreated the issue. You can paste below code into the browser console and see the same error. I slightly modified trackValueOnNode function but it is essentially what is happening under the hood.
const trackValueOnNode = (node) => {
const valueField = 'value'
const descriptor = Object.getOwnPropertyDescriptor(node.constructor.prototype, valueField);
let currentValue = '' + node[valueField];
if (node.hasOwnProperty(valueField) || typeof descriptor === 'undefined' || typeof descriptor.get !== 'function' || typeof descriptor.set !== 'function') {
return;
}
const get = descriptor.get,
set = descriptor.set;
Object.defineProperty(node, valueField, {
configurable: true,
get: function () {
return get.call(this);
},
set: function (value) {
currentValue = '' + value;
set.call(this, value);
}
});
}
const node = document.createElement('input');
trackValueOnNode(node);
const proxy = new Proxy(node, {});
proxy.value = 'f'
The issue could have been prevented if NumberInput didn't wrap ref in a proxy. Or if react didn't track value on node.
React just doesn't expect that ref is overwritten with a ref that is wrapped in a proxy.