Val*_*rio 7 typescript reactjs react-hooks react-hook-form
在我的 React(w/ typescript)应用程序中,我使用react-hook-form 创建了一个表单来管理它的所有逻辑。
然后我用一些 css 和其他东西自定义了 select 元素。但是,为了问题简单起见,这里是准系统组件:
import { forwardRef } from 'react';
type Props = React.DetailedHTMLProps<React.InputHTMLAttributes<HTMLSelectElement>, HTMLSelectElement>;
const Select = forwardRef<HTMLSelectElement, Props>((props, ref) => {
return (
<select ref={ref} {...props}>
<option value="">...</option>
{props.children}
</select>
);
});
export default Select;
Run Code Online (Sandbox Code Playgroud)
然后,我定义了另一个“专门化”前一个组件的组件,如下所示:
import { forwardRef } from 'react';
import Select from './select';
type Props = React.DetailedHTMLProps<React.InputHTMLAttributes<HTMLSelectElement>, HTMLSelectElement> & { label: string; errors?: string };
const SelectWitLargeData = forwardRef<HTMLSelectElement, Props>((props, ref) => {
return (
<Select ref={ref} {...props}>
...large amount of options
</Select>
);
});
export default SelectWitLargeData;
Run Code Online (Sandbox Code Playgroud)
问题是编译器在 <Select ref={ref} (<- here) ...>上给我一个错误
Type 'ForwardedRef<HTMLSelectElement> | LegacyRef<HTMLSelectElement>' is not assignable to type 'Ref<HTMLSelectElement>'.
Type 'string' is not assignable to type 'Ref<HTMLSelectElement>'.ts(2322)
index.d.ts(140, 9): The expected type comes from property 'ref' which is declared here on
type 'IntrinsicAttributes & Pick<Props, "label" | "key" | keyof InputHTMLAttributes<HTMLSelectElement> | "errors"> & RefAttributes<...>'
(JSX attribute) RefAttributes<HTMLSelectElement>.ref?: Ref<HTMLSelectElement>
Run Code Online (Sandbox Code Playgroud)
我在网上搜索了解决方案,并找到了很多建议,但这些都不起作用。
如有任何帮助,请提前致谢!
编辑 这是一个使用组件的示例表单
import { useEffect } from 'react';
import { useForm } from 'react-hook-form';
import Select from '@components/select';
import SelectWithLargeData from '@components/select-with-large-data';
type Form = {
email: string;
state: string;
country: string;
};
const Address: React.FC = () => {
const { handleSubmit, register, setValue } = useForm<Form>();
useEffect(() => {
setValue('state', 'AL');
}, [setValue]);
const onSubmit = async (input: Form) => {
console.log(input);
};
return (
<>
<form onSubmit={handleSubmit(onSubmit)} className="space-y-10">
<input type="email" {...register('email', { required: true })} />
<SelectWithLargeData label="Provincia" {...register('state', { required: true })} />
<Select label="Stato" {...register('country', { required: true })}>
<option value="IT">Italia</option>
</Select>
</form>
</>
);
};
export default Address;
Run Code Online (Sandbox Code Playgroud)
编辑2 https://codesandbox.io/s/withered-rain-w9ej4
请参阅转发参考文档:
const FancyButton = React.forwardRef((props, ref) => (
<button ref={ref} className="FancyButton">
{props.children}
</button>
));
// You can now get a ref directly to the DOM button:
const ref = React.createRef();
<FancyButton ref={ref}>Click me!</FancyButton>;
Run Code Online (Sandbox Code Playgroud)
您应该ref
在内部创建SelectWitLargeData
而不是再次转发。
考虑这个例子:
import React, { forwardRef } from 'react';
type Props = React.DetailedHTMLProps<React.InputHTMLAttributes<HTMLSelectElement>, HTMLSelectElement>;
const Select = forwardRef<HTMLSelectElement, Props>((props, ref) => {
return (
<select ref={ref} {...props}>
<option value="">...</option>
{props.children}
</select>
);
});
type SelectHigherOrder = Props & { label: string; errors?: string };
const SelectWitLargeData = (props: Omit<SelectHigherOrder, 'ref'>) => {
const ref = React.useRef<HTMLSelectElement>(null);
return (
<Select ref={ref} {...props}>
1
</Select>
);
}
Run Code Online (Sandbox Code Playgroud)
您可能已经注意到我已经使用了Omit<SelectHigherOrder, 'ref'>
. 这是因为您使用的是这种类型:React.DetailedHTMLProps<React.InputHTMLAttributes<HTMLSelectElement>, HTMLSelectElement>;
。并且此类型包含遗留引用类型:当您实际覆盖正确的引用类型之后type WithLegacyRef = Props['ref']
使用时,这是{...props}
ref={ref}
React.RefObject<HTMLSelectElement>
归档时间: |
|
查看次数: |
4247 次 |
最近记录: |