英文:
How can Typescript correctly infer generics in react component props?
问题
以下是您要翻译的部分:
只是为了上下文,我正在创建一个组件,如果子元素溢出,它会显示一个工具提示。 children
属性是一个渲染函数,因此调用此组件的人可以将 RefObject
分配给子组件的任何 ref 属性(例如:ref、itemRef、inputRef 等),以及应该调用的事件 onMouseEnter
。
import { TooltipProps } from '@mui/material';
export type OverflowTooltipProps = Omit<TooltipProps, 'children'> & {
children: <RefElem extends HTMLElement>(
ref: RefObject<RefElem>,
onMouseEnter: () => void
) => ReactElement;
};
const OverflowTooltip = <RefElem extends HTMLElement>(props: OverflowTooltipProps) => {
const { children, disableHoverListener, ...other } = props;
const [overflowing, setOverflowing] = useState(false);
const childrenRef = useRef<RefElem>(null);
const testIfOverflowing = () => {
const scrollWidth = childrenRef.current?.scrollWidth;
const clientWidth = childrenRef.current?.clientWidth;
if (scrollWidth && clientWidth) {
setOverflowing(scrollWidth > clientWidth);
}
};
useEffect(() => {
testIfOverflowing();
window.addEventListener('resize', testIfOverflowing);
return () => window.removeEventListener('resize', testIfOverflowing);
}, [children]);
return (
<Tooltip disableHoverListener={disableHoverListener || !overflowing} {...other}>
{children<RefElem>(childrenRef, testIfOverflowing)}
</Tooltip>
);
};
这是一个(简化的)用例:
<OverflowTooltip title={attachment.file.name}>
{(ref, onMouseEnter) => (
<Chip ref={ref} label={attachment.file.name} onMouseEnter={onMouseEnter} />
)}
</OverflowTooltip>
但是,我收到以下错误:
我做错了什么?这不应该根据使用的泛型正确推断吗?
英文:
Just for context, I'm creating a component that shows a Tooltip if the child element is overflowing. children
prop is a render function so whoever calls this component can assign the RefObject
to whichever ref prop of the child component it wants (i.e.: ref, itemRef, inputRef,..), as well as the event that should be called onMouseEnter
.
import { TooltipProps } from '@mui/material';
export type OverflowTooltipProps = Omit<TooltipProps, 'children'> & {
children: <RefElem extends HTMLElement>(
ref: RefObject<RefElem>,
onMouseEnter: () => void
) => ReactElement;
};
const OverflowTooltip = <RefElem extends HTMLElement>(props: OverflowTooltipProps) => {
const { children, disableHoverListener, ...other } = props;
const [overflowing, setOverflowing] = useState(false);
const childrenRef = useRef<RefElem>(null);
const testIfOverflowing = () => {
const scrollWidth = childrenRef.current?.scrollWidth;
const clientWidth = childrenRef.current?.clientWidth;
if (scrollWidth && clientWidth) {
setOverflowing(scrollWidth > clientWidth);
}
};
useEffect(() => {
testIfOverflowing();
window.addEventListener('resize', testIfOverflowing);
return () => window.removeEventListener('resize', testIfOverflowing);
}, [children]);
return (
<Tooltip disableHoverListener={disableHoverListener || !overflowing} {...other}>
{children<RefElem>(childrenRef, testIfOverflowing)}
</Tooltip>
);
};
This is a (simplified) use case:
<OverflowTooltip title={attachment.file.name}>
{(ref, onMouseEnter) => (
<Chip ref={ref} label={attachment.file.name} onMouseEnter={onMouseEnter} />
)}
</OverflowTooltip>
However, I get the following error:
What am I doing wrong? Shouldn't this be inferred correctly because of the generics being used?
答案1
得分: 2
这是您要翻译的代码部分:
import { Chip, Tooltip, TooltipProps } from "@mui/material";
import { ReactElement, RefObject, useEffect, useRef, useState } from "react";
export type OverflowTooltipProps<RefElem extends HTMLElement> = Omit<
TooltipProps,
"children"
> & {
children: (ref: RefObject<RefElem>, onMouseEnter: () => void) => ReactElement;
};
const OverflowTooltip = <RefElem extends HTMLElement>(
props: OverflowTooltipProps<RefElem>
) => {
const { children, disableHoverListener, ...other } = props;
const [overflowing, setOverflowing] = useState(false);
const childrenRef = useRef<RefElem>(null);
const testIfOverflowing = () => {
const scrollWidth = childrenRef.current?.scrollWidth;
const clientWidth = childrenRef.current?.clientWidth;
if (scrollWidth && clientWidth) {
setOverflowing(scrollWidth > clientWidth);
}
};
useEffect(() => {
testIfOverflowing();
window.addEventListener("resize", testIfOverflowing);
return () => window.removeEventListener("resize", testIfOverflowing);
}, [children]);
return (
<Tooltip
disableHoverListener={disableHoverListener || !overflowing}
{...other}
>
{children(childrenRef, testIfOverflowing)}
</Tooltip>
);
};
const attachment = {
file: {
name: "test",
},
};
const App = () => {
<OverflowTooltip<HTMLDivElement> title={attachment.file.name}>
{(ref, onMouseEnter) => (
<Chip
ref={ref}
label={attachment.file.name}
onMouseEnter={onMouseEnter}
/>
)}
</OverflowTooltip>;
};
如果您需要进一步的帮助,请告诉我。
英文:
You actually have to pass generic into to type also. Here you have working solution:
import { Chip, Tooltip, TooltipProps } from "@mui/material";
import { ReactElement, RefObject, useEffect, useRef, useState } from "react";
export type OverflowTooltipProps<RefElem extends HTMLElement> = Omit<
TooltipProps,
"children"
> & {
children: (ref: RefObject<RefElem>, onMouseEnter: () => void) => ReactElement;
};
const OverflowTooltip = <RefElem extends HTMLElement>(
props: OverflowTooltipProps<RefElem>
) => {
const { children, disableHoverListener, ...other } = props;
const [overflowing, setOverflowing] = useState(false);
const childrenRef = useRef<RefElem>(null);
const testIfOverflowing = () => {
const scrollWidth = childrenRef.current?.scrollWidth;
const clientWidth = childrenRef.current?.clientWidth;
if (scrollWidth && clientWidth) {
setOverflowing(scrollWidth > clientWidth);
}
};
useEffect(() => {
testIfOverflowing();
window.addEventListener("resize", testIfOverflowing);
return () => window.removeEventListener("resize", testIfOverflowing);
}, [children]);
return (
<Tooltip
disableHoverListener={disableHoverListener || !overflowing}
{...other}
>
{children(childrenRef, testIfOverflowing)}
</Tooltip>
);
};
const attachment = {
file: {
name: "test",
},
};
const App = () => {
<OverflowTooltip<HTMLDivElement> title={attachment.file.name}>
{(ref, onMouseEnter) => (
<Chip
ref={ref}
label={attachment.file.name}
onMouseEnter={onMouseEnter}
/>
)}
</OverflowTooltip>;
};
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论