reactjs - 在 React 中,使用 TypeScript,如何使用 RefForwardingComponent 和 forwardRef 将 ref 传递给自定义组件?
问题描述
我正在尝试将 ref 传递给自定义组件(以便我可以将焦点设置到组件)。
但我不断收到此错误
const RefComp: React.RefForwardingComponent<HTMLInputElement, Props>
Type '{ value: string; onChange: Dispatch<SetStateAction<string>>; ref: MutableRefObject<HTMLInputElement | undefined>; }'
is not assignable to type 'IntrinsicAttributes & Props & { children?: ReactNode; }'.
Property 'ref' does not exist on type 'IntrinsicAttributes & Props & { children?: ReactNode; }'.ts(2322)
这是我的代码
import * as React from 'react';
import {useRef, useState, RefForwardingComponent, forwardRef} from 'react';
interface Props {
value: string;
onChange(event: string): void;
}
const RefComp: RefForwardingComponent<HTMLInputElement, Props> = forwardRef<
HTMLInputElement,
Props
>(({value, onChange}, ref) => (
<input
value={value}
onChange={event => onChange(event.target.value)}
ref={ref}
/>
));
export default function App() {
const [val, setVal] = useState('');
const inputRef = useRef<HTMLInputElement>();
return (
<div className="App">
<RefComp value={val} onChange={setVal} ref={inputRef} />
<p>{val}</p>
</div>
);
}
这是一个密码箱 https://codesandbox.io/s/crimson-cdn-klfp5
如果我忽略错误,代码似乎工作正常。所以不知道为什么我得到它......
谁能解释我为什么会收到错误,以及如何解决它?:)
编辑:
ref
如评论中所述,您可以通过添加道具来解决此问题。
import * as React from 'react';
import {
useRef,
useState,
RefForwardingComponent,
forwardRef,
MutableRefObject,
} from 'react';
interface Props {
value: string;
onChange(event: string): void;
ref?: MutableRefObject<HTMLInputElement | null>;
}
const RefComp: RefForwardingComponent<HTMLInputElement, Props> = forwardRef<
HTMLInputElement,
Props
>(({value, onChange}, ref) => (
<input
value={value}
onChange={event => onChange(event.target.value)}
ref={ref}
/>
));
export default function App() {
const [val, setVal] = useState('');
const inputRef = useRef<HTMLInputElement>(null);
return (
<div className="App">
<RefComp value={val} onChange={setVal} ref={inputRef} />
<p>{val}</p>
</div>
);
}
但这感觉不对。现在我们说我们ref
既作为 props 的一部分,又作为传递给函数的第二个回调参数forwardRef
如果我这样写,我的问题可能会更清楚
const RefComp: RefForwardingComponent<HTMLInputElement, Props> = forwardRef<
HTMLInputElement,
Props
>((props: Props, ref) => (
<input
value={props.value}
onChange={event => props.onChange(event.target.value)}
ref={ref /* here, props.ref is also available, but wouldn't work */ }
/>
));
编辑2:
这是一个相关的问题
编辑 3:
function forwardRef<T, P = {}>(Component: RefForwardingComponent<T, P>): ForwardRefExoticComponent<PropsWithoutRef<P> & RefAttributes<T>>;
所以该forwardRef
函数返回一个类型为 的组件ForwardRefExoticComponent<PropsWithoutRef<P> & RefAttributes<T>>
。这是一个组件,它采用与PropsWithoutRef<P>
相交的类型的道具RefAttributes<T>
。这两种类型也在同一个文件中定义。
据我了解,第一个基本上只是ref
从 P 中排除(Props
在我的原始示例中)。第二个定义为
interface RefAttributes<T> extends Attributes {
ref?: Ref<T>;
}
鉴于这些信息,我真的不明白为什么我必须添加ref
到我自己的Props
. 它真的看起来好像forwardRef
应该为我做 - 甚至实际上ref
从我自己的身上移除Props
......
有人可以解释一下这里发生了什么吗?
解决方案
问题是RefComp
. 删除它(让 TypeScript 来推断类型),代码就可以正常工作了。
import * as React from 'react';
import {useRef, useState, forwardRef} from 'react';
interface Props {
value: string;
onChange(event: string): void;
}
const RefComp = forwardRef<HTMLInputElement, Props>(
({value, onChange}, ref) => (
<input
value={value}
onChange={event => onChange(event.target.value)}
ref={ref}
/>
),
);
export default function App() {
const [val, setVal] = useState('');
const inputRef = useRef<HTMLInputElement>(null);
React.useEffect(() => {
if (inputRef.current) {
inputRef.current.focus();
}
}, []);
return (
<div className="App">
<RefComp value={val} onChange={setVal} ref={inputRef} />
<p>{val}</p>
</div>
);
}
推荐阅读
- wordpress - 如何添加更多社交分享按钮
- android - Android 似乎忽略了我对 onActivityResult 的 setResult 调用
- mysql - 向同一个表添加 SQL 约束
- mysql - 从生成的大型查询中修剪尾随 mysql group_concat
- android - 用户输入验证仅包含字母字符
- javascript - 在javascript中,在一个函数中过滤和映射数组?
- insert - 在一个查询中插入表 2 并更新 BigQuery 的表 2
- python - 我试图从文本文件中获取列表的平均值
- angular - Firebase + ngrx + 多个身份验证提供商
- python - python线程锁不会锁定线程的其余部分