Improve data prefetching, less false positives
This commit is contained in:
@@ -118,7 +118,7 @@ const CollectionLink: React.FC<Props> = ({
|
|||||||
setIsEditing(isEditing);
|
setIsEditing(isEditing);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const handleMouseEnter = React.useCallback(() => {
|
const handlePrefetch = React.useCallback(() => {
|
||||||
void collection.fetchDocuments();
|
void collection.fetchDocuments();
|
||||||
}, [collection]);
|
}, [collection]);
|
||||||
|
|
||||||
@@ -138,7 +138,7 @@ const CollectionLink: React.FC<Props> = ({
|
|||||||
}}
|
}}
|
||||||
expanded={expanded}
|
expanded={expanded}
|
||||||
onDisclosureClick={onDisclosureClick}
|
onDisclosureClick={onDisclosureClick}
|
||||||
onMouseEnter={handleMouseEnter}
|
onClickIntent={handlePrefetch}
|
||||||
icon={
|
icon={
|
||||||
<CollectionIcon collection={collection} expanded={expanded} />
|
<CollectionIcon collection={collection} expanded={expanded} />
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -114,7 +114,7 @@ function InnerDocumentLink(
|
|||||||
[expanded]
|
[expanded]
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleMouseEnter = React.useCallback(() => {
|
const handlePrefetch = React.useCallback(() => {
|
||||||
prefetchDocument?.(node.id);
|
prefetchDocument?.(node.id);
|
||||||
}, [prefetchDocument, node]);
|
}, [prefetchDocument, node]);
|
||||||
|
|
||||||
@@ -317,7 +317,7 @@ function InnerDocumentLink(
|
|||||||
<SidebarLink
|
<SidebarLink
|
||||||
expanded={hasChildren ? isExpanded : undefined}
|
expanded={hasChildren ? isExpanded : undefined}
|
||||||
onDisclosureClick={handleDisclosureClick}
|
onDisclosureClick={handleDisclosureClick}
|
||||||
onMouseEnter={handleMouseEnter}
|
onClickIntent={handlePrefetch}
|
||||||
to={{
|
to={{
|
||||||
pathname: node.url,
|
pathname: node.url,
|
||||||
state: {
|
state: {
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import { s } from "@shared/styles";
|
|||||||
import { NavigationNode } from "@shared/types";
|
import { NavigationNode } from "@shared/types";
|
||||||
import EventBoundary from "~/components/EventBoundary";
|
import EventBoundary from "~/components/EventBoundary";
|
||||||
import NudeButton from "~/components/NudeButton";
|
import NudeButton from "~/components/NudeButton";
|
||||||
|
import useUnmount from "~/hooks/useUnmount";
|
||||||
import { undraggableOnDesktop } from "~/styles";
|
import { undraggableOnDesktop } from "~/styles";
|
||||||
import Disclosure from "./Disclosure";
|
import Disclosure from "./Disclosure";
|
||||||
import NavLink, { Props as NavLinkProps } from "./NavLink";
|
import NavLink, { Props as NavLinkProps } from "./NavLink";
|
||||||
@@ -20,7 +21,8 @@ type Props = Omit<NavLinkProps, "to"> & {
|
|||||||
to?: LocationDescriptor;
|
to?: LocationDescriptor;
|
||||||
innerRef?: (ref: HTMLElement | null | undefined) => void;
|
innerRef?: (ref: HTMLElement | null | undefined) => void;
|
||||||
onClick?: React.MouseEventHandler<HTMLAnchorElement>;
|
onClick?: React.MouseEventHandler<HTMLAnchorElement>;
|
||||||
onMouseEnter?: React.MouseEventHandler<HTMLAnchorElement>;
|
/* Callback when we expect the user to click on the link. Used for prefetching data. */
|
||||||
|
onClickIntent?: () => void;
|
||||||
onDisclosureClick?: React.MouseEventHandler<HTMLButtonElement>;
|
onDisclosureClick?: React.MouseEventHandler<HTMLButtonElement>;
|
||||||
icon?: React.ReactNode;
|
icon?: React.ReactNode;
|
||||||
label?: React.ReactNode;
|
label?: React.ReactNode;
|
||||||
@@ -44,7 +46,7 @@ function SidebarLink(
|
|||||||
{
|
{
|
||||||
icon,
|
icon,
|
||||||
onClick,
|
onClick,
|
||||||
onMouseEnter,
|
onClickIntent,
|
||||||
to,
|
to,
|
||||||
label,
|
label,
|
||||||
active,
|
active,
|
||||||
@@ -63,6 +65,7 @@ function SidebarLink(
|
|||||||
}: Props,
|
}: Props,
|
||||||
ref: React.RefObject<HTMLAnchorElement>
|
ref: React.RefObject<HTMLAnchorElement>
|
||||||
) {
|
) {
|
||||||
|
const timer = React.useRef<number>();
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const style = React.useMemo(
|
const style = React.useMemo(
|
||||||
() => ({
|
() => ({
|
||||||
@@ -81,6 +84,28 @@ function SidebarLink(
|
|||||||
[theme.text, theme.sidebarActiveBackground, style]
|
[theme.text, theme.sidebarActiveBackground, style]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const handleMouseEnter = React.useCallback(() => {
|
||||||
|
if (timer.current) {
|
||||||
|
clearTimeout(timer.current);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (onClickIntent) {
|
||||||
|
timer.current = window.setTimeout(onClickIntent, 100);
|
||||||
|
}
|
||||||
|
}, [onClickIntent]);
|
||||||
|
|
||||||
|
const handleMouseLeave = React.useCallback(() => {
|
||||||
|
if (timer.current) {
|
||||||
|
clearTimeout(timer.current);
|
||||||
|
}
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
useUnmount(() => {
|
||||||
|
if (timer.current) {
|
||||||
|
clearTimeout(timer.current);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Link
|
<Link
|
||||||
@@ -90,7 +115,8 @@ function SidebarLink(
|
|||||||
activeStyle={isActiveDrop ? activeDropStyle : activeStyle}
|
activeStyle={isActiveDrop ? activeDropStyle : activeStyle}
|
||||||
style={active ? activeStyle : style}
|
style={active ? activeStyle : style}
|
||||||
onClick={onClick}
|
onClick={onClick}
|
||||||
onMouseEnter={onMouseEnter}
|
onMouseEnter={handleMouseEnter}
|
||||||
|
onMouseLeave={handleMouseLeave}
|
||||||
// @ts-expect-error exact does not exist on div
|
// @ts-expect-error exact does not exist on div
|
||||||
exact={exact !== false}
|
exact={exact !== false}
|
||||||
to={to}
|
to={to}
|
||||||
|
|||||||
Reference in New Issue
Block a user