我有两个组件:App
和Child
。我使用useRef
钩子来获取Child
组件中的DOM元素,并对它做一些工作。
我还使用React.forwardRef
API将ref
从App
组件传递到Child
组件。App.tsx
:
import { useRef } from "react";
import Child from "./Child";
export default function App() {
const ref = useRef(null);
console.log("App ref: ", ref);
return (
<div className="App">
<Child ref={ref} />
</div>
);
}
Child.ts
:
import React, { useEffect, useRef } from "react";
export default React.forwardRef((props, ref) => {
const innerRef = useRef<HTMLDivElement>(null);
const divElement = ref || innerRef; // TSC throw error here.
useEffect(() => {
if (divElement.current) {
console.log("clientWidth: ", divElement.current.clientWidth);
// do something with divElement.current
}
}, []);
return <div ref={divElement}></div>;
});
我不确定像上面那样一起使用innerRef
和转发ref
是否正确。至少,TSC抛出一个错误,这意味着它不允许这样使用它。
类型'((示例:unknown)=> void)|MutableRefObject '不可分配给类型' string|((示例:HTMLDivElement| null)=> void)|RefObject|零|未定义类型“MutableRefObject”不可分配给类型“string|((示例:HTMLDivElement| null)=> void)|RefObject|零|未定义类型“MutableRefObject”不能分配给类型“RefObject”。属性“current”的类型不兼容。类型“unknown”不能分配给类型“HTMLDivElement| null'.类型'unknown'不可分配给类型'HTMLDivElement'. ts(2322)index. d. ts(143,9):预期的类型来自属性“ref”,该属性在类型“DetailedHTMLProps <HTMLAttributes,HTMLDivElement>”上声明
我想在App
组件中获得正确的ref,并在Child组件中使用此ref
。我该怎么做?
codesandbox
2条答案
按热度按时间igetnqfo1#
您可以在很大程度上忽略TS错误,因为您没有为forwardRef参数提供类型,因此它不知道ref/innerRef是等效类型的。
const divElement = ref || innerRef;
<div ref={divElement}></div>
我不明白这一点--你想让它直接引用div元素,而不管是否给了一个ref?
无论如何,我认为如果你想让它像这样工作,最好使用
useImperativeHandle
钩子,比如useImperativeHandle(ref, () => innerRef.current);
因此,Child组件本身使用
innerRef
管理ref,但如果有人向Child组件传递ref,它将产生该ref。esbemjvw2#
如果你正在寻找一个使用TypeScript而不使用
useImperativeHandle
的解决方案,你可以这样写:示例:https://codesandbox.io/s/beautiful-shadow-n83nmw?file=/src/App.tsx
它工作的原因是
ref
prop 接受回调,因此当它触发时,您可以执行任何您喜欢的代码。这里,我们设置了ref
值(我们说它可以是一个函数,因此if
/else
)和innerRef
。注意:
useImperativeHandle
没有任何问题,请随意使用。两种解决方案的性能相同。