I have this wrapper component for the mui Tooltip
component with the added functionality that it automatically closes the tooltip when the table around it is being scrolled. The code works well but I want to improve the code quality since there are a few duplicate lines. Also I believe there should be a way to find the reference to the table once and use it in all three function calls. Any help would be appreciated and I apologise for such a generic question. I don’t know how to make it more specific.
import { TooltipProps } from '@mui/material';
import { useRef, useState } from 'react';
import { Tooltip } from '../tooltip/Tooltip';
interface TableTooltipProps extends TooltipProps {
selector?: string;
}
export function TableTooltip({
selector = '.MuiTableContainer-root',
children,
...props
}: TableTooltipProps) {
const [isScrolling, setIsScrolling] = useState(false);
const [timeoutId, setTimeoutId] = useState<number>(null);
const ref = useRef<any>();
const handleScroll = () => {
console.warn('scrolling');
setIsScrolling(true);
if (ref.current) {
ref.current.closest(selector).removeEventListener('scroll', handleScroll);
console.warn('aborted');
}
clearTimeout(timeoutId);
setTimeoutId(
window.setTimeout(() => {
setIsScrolling(false);
}, 500),
);
};
const attachToScrollEvent = () => {
if (ref.current) {
console.warn('added');
const tableElement = ref.current.closest(selector);
tableElement.addEventListener('scroll', handleScroll);
}
};
const detachFromScrollEvent = () => {
if (ref.current) {
console.warn('removed');
const tableElement = ref.current.closest(selector);
tableElement.removeEventListener('scroll', handleScroll);
}
};
return !isScrolling ? (
<>
<Tooltip
onOpenCallback={attachToScrollEvent}
onCloseCallback={detachFromScrollEvent}
{...props}
>
{children}
</Tooltip>
<td className="html-element-dummy" style={{ display: 'none' }} ref={ref} />
</>
) : (
<>{children}</>
);
}
2
Answers
I figured out a way to improve my own code. The answer by @Wesley unfortunately had some undesirable side effects.
I am just not sure whether useCallback is necessary here.
A simple refactor using
optional chaining
would allow you to reduce code by ignoring the error when the ref is initially undefined for an insignificant period of time, on the.closest
and theaddEventListener
/removeEventListener
calls.