refactor(widgets): stabilize widget components after useQuery migration
Add WidgetEmptyState component for widgets that need a loading fallback. Disable refetch-on-mount/focus/reconnect and retry for integration widgets so cached data is preserved. Ensure hooks are never called conditionally.
This commit is contained in:
1 parent
f7f6d1e382
commit
f49ae79c99
17 files changed
+59
-20
No files matched your search
@@ -3,7 +3,7 @@
|
||||
import type { PropsWithChildren } from "react";
|
||||
import { Fragment, Suspense } from "react";
|
||||
import { Flex, rem, Stack, Text, Tooltip, UnstyledButton } from "@mantine/core";
|
||||
import { IconLoader } from "@tabler/icons-react";
|
||||
import { IconMinus } from "@tabler/icons-react";
|
||||
import combineClasses from "clsx";
|
||||
|
||||
import { clientApi } from "@homarr/api/client";
|
||||
@@ -13,6 +13,7 @@ import { useRegisterSpotlightContextResults } from "@homarr/spotlight";
|
||||
import { useI18n } from "@homarr/translation/client";
|
||||
import { MaskedOrNormalImage } from "@homarr/ui";
|
||||
|
||||
import { WidgetEmptyState } from "../common/empty-state";
|
||||
import type { WidgetComponentProps } from "../definition";
|
||||
import classes from "./app.module.css";
|
||||
import { PingDot } from "./ping/ping-dot";
|
||||
@@ -55,7 +56,7 @@ export default function AppWidget({ options, isEditMode, height, width }: Widget
|
||||
[app, options.openInNewTab],
|
||||
);
|
||||
|
||||
if (!app) return null;
|
||||
if (!app) return <WidgetEmptyState />;
|
||||
|
||||
const isTiny = height < 100 || width < 100;
|
||||
const isColumnLayout = options.layout.startsWith("column");
|
||||
@@ -131,7 +132,7 @@ export default function AppWidget({ options, isEditMode, height, width }: Widget
|
||||
</Flex>
|
||||
</Tooltip.Floating>
|
||||
{options.pingEnabled && !settings.forceDisableStatus && !board.disableStatus && app.href ? (
|
||||
<Suspense fallback={<PingDot icon={IconLoader} color="blue" tooltip={`${t("common.action.loading")}…`} />}>
|
||||
<Suspense fallback={<PingDot icon={IconMinus} color="gray" tooltip={`${t("common.action.loading")}…`} />}>
|
||||
<PingIndicator appId={app.id} />
|
||||
</Suspense>
|
||||
) : null}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { IconCheck, IconX } from "@tabler/icons-react";
|
||||
import { IconCheck, IconMinus, IconX } from "@tabler/icons-react";
|
||||
|
||||
import { clientApi } from "@homarr/api/client";
|
||||
import { useI18n } from "@homarr/translation/client";
|
||||
|
||||
import { PingDot } from "./ping-dot";
|
||||
|
||||
@@ -9,6 +10,7 @@ interface PingIndicatorProps {
|
||||
}
|
||||
|
||||
export const PingIndicator = ({ appId }: PingIndicatorProps) => {
|
||||
const t = useI18n();
|
||||
const { data: pingResult } = clientApi.widget.app.ping.useQuery(
|
||||
{ id: appId },
|
||||
{ refetchOnMount: false, refetchOnWindowFocus: false },
|
||||
@@ -24,7 +26,7 @@ export const PingIndicator = ({ appId }: PingIndicatorProps) => {
|
||||
},
|
||||
);
|
||||
|
||||
if (!pingResult) return null;
|
||||
if (!pingResult) return <PingDot icon={IconMinus} color="gray" tooltip={`${t("common.action.loading")}…`} />;
|
||||
|
||||
const isError = "error" in pingResult || pingResult.statusCode >= 500;
|
||||
|
||||
|
||||
Reference in new issue
Block a user