From 0dcf56ef18a9058def2851d837162faaadb77406 Mon Sep 17 00:00:00 2001 From: Marc Brooks Date: Mon, 13 Oct 2025 20:11:58 -0500 Subject: [PATCH] Fix UI lint warnings There were a bunch of ref and useEffect violations. --- .../devices.$id.settings.general.update.tsx | 9 -- .../routes/devices.$id.settings.hardware.tsx | 56 +++++++------ .../routes/devices.$id.settings.network.tsx | 82 +++++++++---------- ui/src/routes/devices.$id.settings.video.tsx | 3 +- 4 files changed, 73 insertions(+), 77 deletions(-) diff --git a/ui/src/routes/devices.$id.settings.general.update.tsx b/ui/src/routes/devices.$id.settings.general.update.tsx index 38c15412..48c87f3d 100644 --- a/ui/src/routes/devices.$id.settings.general.update.tsx +++ b/ui/src/routes/devices.$id.settings.general.update.tsx @@ -41,8 +41,6 @@ export default function SettingsGeneralUpdateRoute() { return navigate("..")} onConfirmUpdate={onConfirmUpdate} />; } - - export function Dialog({ onClose, onConfirmUpdate, @@ -71,11 +69,6 @@ export function Dialog({ [setModalView], ); - // Reset modal view when dialog is opened - useEffect(() => { - setVersionInfo(null); - }, [setModalView]); - return (
@@ -133,8 +126,6 @@ function LoadingState({ const progressBarRef = useRef(null); useEffect(() => { - setProgressWidth("0%"); - abortControllerRef.current = new AbortController(); const signal = abortControllerRef.current.signal; diff --git a/ui/src/routes/devices.$id.settings.hardware.tsx b/ui/src/routes/devices.$id.settings.hardware.tsx index 9475f4fe..9ee999ee 100644 --- a/ui/src/routes/devices.$id.settings.hardware.tsx +++ b/ui/src/routes/devices.$id.settings.hardware.tsx @@ -1,20 +1,19 @@ import { useEffect } from "react"; +import { BacklightSettings, useSettingsStore } from "@hooks/stores"; +import { JsonRpcResponse, useJsonRpc } from "@hooks/useJsonRpc"; +import { FeatureFlag } from "@components/FeatureFlag"; +import { SelectMenuBasic } from "@components/SelectMenuBasic"; import { SettingsItem } from "@components/SettingsItem"; import { SettingsPageHeader } from "@components/SettingsPageheader"; -import { BacklightSettings, useSettingsStore } from "@/hooks/stores"; -import { JsonRpcResponse, useJsonRpc } from "@/hooks/useJsonRpc"; -import { SelectMenuBasic } from "@components/SelectMenuBasic"; import { UsbDeviceSetting } from "@components/UsbDeviceSetting"; - -import notifications from "../notifications"; -import { UsbInfoSetting } from "../components/UsbInfoSetting"; -import { FeatureFlag } from "../components/FeatureFlag"; +import { UsbInfoSetting } from "@components/UsbInfoSetting"; +import notifications from "@/notifications"; export default function SettingsHardwareRoute() { const { send } = useJsonRpc(); const settings = useSettingsStore(); - const { setDisplayRotation } = useSettingsStore(); + const { displayRotation, setDisplayRotation } = useSettingsStore(); const handleDisplayRotationChange = (rotation: string) => { setDisplayRotation(rotation); @@ -22,7 +21,7 @@ export default function SettingsHardwareRoute() { }; const handleDisplayRotationSave = () => { - send("setDisplayRotation", { params: { rotation: settings.displayRotation } }, (resp: JsonRpcResponse) => { + send("setDisplayRotation", { params: { rotation: displayRotation } }, (resp: JsonRpcResponse) => { if ("error" in resp) { notifications.error( `Failed to set display orientation: ${resp.error.data || "Unknown error"}`, @@ -33,7 +32,7 @@ export default function SettingsHardwareRoute() { }); }; - const { setBacklightSettings } = useSettingsStore(); + const { backlightSettings, setBacklightSettings } = useSettingsStore(); const handleBacklightSettingsChange = (settings: BacklightSettings) => { // If the user has set the display to dim after it turns off, set the dim_after @@ -47,7 +46,7 @@ export default function SettingsHardwareRoute() { }; const handleBacklightSettingsSave = () => { - send("setBacklightSettings", { params: settings.backlightSettings }, (resp: JsonRpcResponse) => { + send("setBacklightSettings", { params: backlightSettings }, (resp: JsonRpcResponse) => { if ("error" in resp) { notifications.error( `Failed to set backlight settings: ${resp.error.data || "Unknown error"}`, @@ -58,6 +57,21 @@ export default function SettingsHardwareRoute() { }); }; + const handleBacklightMaxBrightnessChange = (max_brightness: number) => { + const settings = { ...backlightSettings, max_brightness }; + handleBacklightSettingsChange(settings); + }; + + const handleBacklightDimAfterChange = (dim_after: number) => { + const settings = { ...backlightSettings, dim_after }; + handleBacklightSettingsChange(settings); + }; + + const handleBacklightOffAfterChange = (off_after: number) => { + const settings = { ...backlightSettings, off_after }; + handleBacklightSettingsChange(settings); + }; + useEffect(() => { send("getBacklightSettings", {}, (resp: JsonRpcResponse) => { if ("error" in resp) { @@ -90,8 +104,7 @@ export default function SettingsHardwareRoute() { { value: "90", label: "Inverted" }, ]} onChange={e => { - settings.displayRotation = e.target.value; - handleDisplayRotationChange(settings.displayRotation); + handleDisplayRotationChange(e.target.value); }} /> @@ -102,7 +115,7 @@ export default function SettingsHardwareRoute() { { - settings.backlightSettings.max_brightness = parseInt(e.target.value); - handleBacklightSettingsChange(settings.backlightSettings); + handleBacklightMaxBrightnessChange(parseInt(e.target.value)); }} /> - {settings.backlightSettings.max_brightness != 0 && ( + {backlightSettings.max_brightness != 0 && ( <> { - settings.backlightSettings.dim_after = parseInt(e.target.value); - handleBacklightSettingsChange(settings.backlightSettings); + handleBacklightDimAfterChange(parseInt(e.target.value)); }} /> @@ -146,7 +157,7 @@ export default function SettingsHardwareRoute() { { - settings.backlightSettings.off_after = parseInt(e.target.value); - handleBacklightSettingsChange(settings.backlightSettings); + handleBacklightOffAfterChange(parseInt(e.target.value)); }} /> diff --git a/ui/src/routes/devices.$id.settings.network.tsx b/ui/src/routes/devices.$id.settings.network.tsx index 5f4dc90f..1c0ecb2c 100644 --- a/ui/src/routes/devices.$id.settings.network.tsx +++ b/ui/src/routes/devices.$id.settings.network.tsx @@ -1,4 +1,4 @@ -import { useCallback, useEffect, useRef, useState } from "react"; +import { useCallback, useEffect, useMemo, useState } from "react"; import dayjs from "dayjs"; import relativeTime from "dayjs/plugin/relativeTime"; import { LuEthernetPort } from "react-icons/lu"; @@ -12,23 +12,22 @@ import { NetworkState, TimeSyncMode, useNetworkStateStore, -} from "@/hooks/stores"; -import { JsonRpcResponse, useJsonRpc } from "@/hooks/useJsonRpc"; +} from "@hooks/stores"; +import { JsonRpcResponse, useJsonRpc } from "@hooks/useJsonRpc"; +import AutoHeight from "@components/AutoHeight"; import { Button } from "@components/Button"; +import { ConfirmDialog } from "@components/ConfirmDialog"; +import EmptyCard from "@components/EmptyCard"; +import Fieldset from "@components/Fieldset"; import { GridCard } from "@components/Card"; import InputField, { InputFieldWithLabel } from "@components/InputField"; -import { SelectMenuBasic } from "@/components/SelectMenuBasic"; -import { SettingsPageHeader } from "@/components/SettingsPageheader"; -import Fieldset from "@/components/Fieldset"; -import { ConfirmDialog } from "@/components/ConfirmDialog"; +import Ipv6NetworkCard from "@components/Ipv6NetworkCard"; +import DhcpLeaseCard from "@components/DhcpLeaseCard"; +import { SelectMenuBasic } from "@components/SelectMenuBasic"; import { SettingsItem } from "@components/SettingsItem"; +import { SettingsPageHeader } from "@components/SettingsPageheader"; import notifications from "@/notifications"; -import Ipv6NetworkCard from "../components/Ipv6NetworkCard"; -import EmptyCard from "../components/EmptyCard"; -import AutoHeight from "../components/AutoHeight"; -import DhcpLeaseCard from "../components/DhcpLeaseCard"; - dayjs.extend(relativeTime); const defaultNetworkSettings: NetworkSettings = { @@ -46,14 +45,18 @@ const defaultNetworkSettings: NetworkSettings = { export function LifeTimeLabel({ lifetime }: { lifetime: string }) { const [remaining, setRemaining] = useState(null); - useEffect(() => { + const updateRemaining = useCallback(() => { setRemaining(dayjs(lifetime).fromNow()); + }, [lifetime]); + + useEffect(() => { + setTimeout(() => updateRemaining(), 0); const interval = setInterval(() => { - setRemaining(dayjs(lifetime).fromNow()); + updateRemaining(); }, 1000 * 30); return () => clearInterval(interval); - }, [lifetime]); + }, [updateRemaining]); if (lifetime == "") { return N/A; @@ -81,24 +84,19 @@ export default function SettingsNetworkRoute() { useState(defaultNetworkSettings); // We use this to determine whether the settings have changed - const firstNetworkSettings = useRef(undefined); - + const [firstNetworkSettings, setFirstNetworkSettings] = useState(undefined); const [networkSettingsLoaded, setNetworkSettingsLoaded] = useState(false); - const [customDomain, setCustomDomain] = useState(""); - const [selectedDomainOption, setSelectedDomainOption] = useState("dhcp"); + const selectedDomainOption = useMemo(() => { + if (!networkSettingsLoaded) return "dhcp"; + const predefinedOptions = ["dhcp", "local"]; + return predefinedOptions.includes(networkSettings.domain) ? networkSettings.domain : "custom"; + }, [networkSettings.domain, networkSettingsLoaded]); - useEffect(() => { - if (networkSettings.domain && networkSettingsLoaded) { - // Check if the domain is one of the predefined options - const predefinedOptions = ["dhcp", "local"]; - if (predefinedOptions.includes(networkSettings.domain)) { - setSelectedDomainOption(networkSettings.domain); - } else { - setSelectedDomainOption("custom"); - setCustomDomain(networkSettings.domain); - } - } + const customDomain = useMemo(() => { + if (!networkSettingsLoaded) return ""; + const predefinedOptions = ["dhcp", "local"]; + return predefinedOptions.includes(networkSettings.domain) ? "" : networkSettings.domain; }, [networkSettings.domain, networkSettingsLoaded]); const getNetworkSettings = useCallback(() => { @@ -109,12 +107,12 @@ export default function SettingsNetworkRoute() { console.debug("Network settings: ", networkSettings); setNetworkSettings(networkSettings); - if (!firstNetworkSettings.current) { - firstNetworkSettings.current = networkSettings; + if (!firstNetworkSettings) { + setFirstNetworkSettings(networkSettings); } setNetworkSettingsLoaded(true); }); - }, [send]); + }, [send, firstNetworkSettings]); const getNetworkState = useCallback(() => { send("getNetworkState", {}, (resp: JsonRpcResponse) => { @@ -132,14 +130,13 @@ export default function SettingsNetworkRoute() { if ("error" in resp) { notifications.error( "Failed to save network settings: " + - (resp.error.data ? resp.error.data : resp.error.message), + (resp.error.data ? resp.error.data : resp.error.message), ); setNetworkSettingsLoaded(true); return; } const networkSettings = resp.result as NetworkSettings; - // We need to update the firstNetworkSettings ref to the new settings so we can use it to determine if the settings have changed - firstNetworkSettings.current = networkSettings; + setFirstNetworkSettings(networkSettings); setNetworkSettings(networkSettings); getNetworkState(); setNetworkSettingsLoaded(true); @@ -160,8 +157,10 @@ export default function SettingsNetworkRoute() { }, [send]); useEffect(() => { - getNetworkState(); - getNetworkSettings(); + setTimeout(() => { + getNetworkState(); + getNetworkSettings(); + }, 0); }, [getNetworkState, getNetworkSettings]); const handleIpv4ModeChange = (value: IPv4Mode | string) => { @@ -197,14 +196,12 @@ export default function SettingsNetworkRoute() { }; const handleDomainOptionChange = (value: string) => { - setSelectedDomainOption(value); if (value !== "custom") { handleDomainChange(value); } }; const handleCustomDomainChange = (value: string) => { - setCustomDomain(value); handleDomainChange(value); }; @@ -309,7 +306,6 @@ export default function SettingsNetworkRoute() { placeholder="home" value={customDomain} onChange={e => { - setCustomDomain(e.target.value); handleCustomDomainChange(e.target.value); }} /> @@ -361,7 +357,7 @@ export default function SettingsNetworkRoute() {