diff options
| author | Tobias Järvelöv <tobias.jarvelov@mullvad.net> | 2025-08-14 14:23:16 +0200 |
|---|---|---|
| committer | Tobias Järvelöv <tobias.jarvelov@mullvad.net> | 2025-08-15 10:12:07 +0200 |
| commit | 0a8fcda430f58d09d5455a70a7b023ed54eefcdb (patch) | |
| tree | 8519858a9685221618b877e24af52780f1b43867 | |
| parent | e6270d07adb63e088e388ae7f5fe181c2d767c1a (diff) | |
| download | mullvadvpn-0a8fcda430f58d09d5455a70a7b023ed54eefcdb.tar.xz mullvadvpn-0a8fcda430f58d09d5455a70a7b023ed54eefcdb.zip | |
Disable linting on React hooks which invokes a useEffectEvent callback
Currently React has not released their useEffectEvent hook[1] in a
stable version and we instead rely on our own implementation of the
hook to achieve the same functionality.
Unfortunately however, the react plugin for eslint does not recognize
useEffectEvent and that it can be omitted from a hook's dependency
array, hence we have to disable that rule until this issue can be
addressed.
Potential fixes will be discussed in the following linear issue:
https://linear.app/mullvad/issue/DES-2381
[1] https://react.dev/reference/react/experimental_useEffectEvent
19 files changed, 135 insertions, 0 deletions
diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/Account.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/Account.tsx index f932139a2b..b7c1f2354a 100644 --- a/desktop/packages/mullvad-vpn/src/renderer/components/Account.tsx +++ b/desktop/packages/mullvad-vpn/src/renderer/components/Account.tsx @@ -37,6 +37,11 @@ export default function Account() { }); const onMount = useEffectEvent(() => updateAccountData()); + // These lint rules are disabled for now because the react plugin for eslint does + // not understand that useEffectEvent should not be added to the dependency array. + // Enable these rules again when eslint can lint useEffectEvent properly. + // eslint-disable-next-line react-compiler/react-compiler + // eslint-disable-next-line react-hooks/exhaustive-deps useEffect(() => onMount(), []); // Hack needed because if we just call `logout` directly in `onClick` diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/KeyboardNavigation.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/KeyboardNavigation.tsx index 2dff95ec5d..79fde5e536 100644 --- a/desktop/packages/mullvad-vpn/src/renderer/components/KeyboardNavigation.tsx +++ b/desktop/packages/mullvad-vpn/src/renderer/components/KeyboardNavigation.tsx @@ -129,6 +129,11 @@ function BackActionTracker(props: IBackActionTracker) { props.registerBackAction(backActions.at(0)); }); + // These lint rules are disabled for now because the react plugin for eslint does + // not understand that useEffectEvent should not be added to the dependency array. + // Enable these rules again when eslint can lint useEffectEvent properly. + // eslint-disable-next-line react-compiler/react-compiler + // eslint-disable-next-line react-hooks/exhaustive-deps useEffect(() => registerBackActionEvent(backActions), [backActions]); return ( diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/List.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/List.tsx index 4961855fba..3773b563e2 100644 --- a/desktop/packages/mullvad-vpn/src/renderer/components/List.tsx +++ b/desktop/packages/mullvad-vpn/src/renderer/components/List.tsx @@ -53,6 +53,11 @@ export default function List<T>(props: ListProps<T>) { }); }); + // These lint rules are disabled for now because the react plugin for eslint does + // not understand that useEffectEvent should not be added to the dependency array. + // Enable these rules again when eslint can lint useEffectEvent properly. + // eslint-disable-next-line react-compiler/react-compiler + // eslint-disable-next-line react-hooks/exhaustive-deps useEffect(() => itemChangeEvent(props.items), [props.items]); useEffect(() => { @@ -79,6 +84,11 @@ export default function List<T>(props: ListProps<T>) { }); }); + // These lint rules are disabled for now because the react plugin for eslint does + // not understand that useEffectEvent should not be added to the dependency array. + // Enable these rules again when eslint can lint useEffectEvent properly. + // eslint-disable-next-line react-compiler/react-compiler + // eslint-disable-next-line react-hooks/exhaustive-deps useEffect(() => handleDisplayItemsChange(displayItems), [displayItems]); useEffect( diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/MacOsScrollbarDetection.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/MacOsScrollbarDetection.tsx index 520b6f3f3b..0e862b7be5 100644 --- a/desktop/packages/mullvad-vpn/src/renderer/components/MacOsScrollbarDetection.tsx +++ b/desktop/packages/mullvad-vpn/src/renderer/components/MacOsScrollbarDetection.tsx @@ -35,6 +35,11 @@ export default function MacOsScrollbarDetection() { } }); + // These lint rules are disabled for now because the react plugin for eslint does + // not understand that useEffectEvent should not be added to the dependency array. + // Enable these rules again when eslint can lint useEffectEvent properly. + // eslint-disable-next-line react-compiler/react-compiler + // eslint-disable-next-line react-hooks/exhaustive-deps useEffect(() => detectVisibility(visibility), [visibility]); return ( diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/Map.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/Map.tsx index d19aa1ae14..a8e41e8078 100644 --- a/desktop/packages/mullvad-vpn/src/renderer/components/Map.tsx +++ b/desktop/packages/mullvad-vpn/src/renderer/components/Map.tsx @@ -126,6 +126,11 @@ function MapInner(props: MapInnerProps) { } }); + // These lint rules are disabled for now because the react plugin for eslint does + // not understand that useEffectEvent should not be added to the dependency array. + // Enable these rules again when eslint can lint useEffectEvent properly. + // eslint-disable-next-line react-compiler/react-compiler + // eslint-disable-next-line react-hooks/exhaustive-deps const render = useCallback(() => requestAnimationFrame(animationFrameCallback), []); // This is called when the canvas has been rendered the first time and initializes the gl context @@ -172,11 +177,21 @@ function MapInner(props: MapInnerProps) { useEffect(() => { addEventListener('resize', onSizeChange); return () => removeEventListener('resize', onSizeChange); + // These lint rules are disabled for now because the react plugin for eslint does + // not understand that useEffectEvent should not be added to the dependency array. + // Enable these rules again when eslint can lint useEffectEvent properly. + // eslint-disable-next-line react-compiler/react-compiler + // eslint-disable-next-line react-hooks/exhaustive-deps }, []); useEffect(() => { const unsubscribe = window.ipc.window.listenScaleFactorChange(onSizeChange); return () => unsubscribe(); + // These lint rules are disabled for now because the react plugin for eslint does + // not understand that useEffectEvent should not be added to the dependency array. + // Enable these rules again when eslint can lint useEffectEvent properly. + // eslint-disable-next-line react-compiler/react-compiler + // eslint-disable-next-line react-hooks/exhaustive-deps }, []); const devicePixelRatio = window.devicePixelRatio; diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/Modal.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/Modal.tsx index cb4af34377..85b73fa82a 100644 --- a/desktop/packages/mullvad-vpn/src/renderer/components/Modal.tsx +++ b/desktop/packages/mullvad-vpn/src/renderer/components/Modal.tsx @@ -193,6 +193,11 @@ export function ModalAlert(props: IModalAlertProps & { isOpen: boolean }) { })); }); + // These lint rules are disabled for now because the react plugin for eslint does + // not understand that useEffectEvent should not be added to the dependency array. + // Enable these rules again when eslint can lint useEffectEvent properly. + // eslint-disable-next-line react-compiler/react-compiler + // eslint-disable-next-line react-hooks/exhaustive-deps useEffect(() => onOpenStateChange(isOpen), [isOpen]); if (!openState.wasOpen && !isOpen && !openState.isClosing) { diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/NavigationScrollbars.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/NavigationScrollbars.tsx index 93188659b1..8aadf5b1c6 100644 --- a/desktop/packages/mullvad-vpn/src/renderer/components/NavigationScrollbars.tsx +++ b/desktop/packages/mullvad-vpn/src/renderer/components/NavigationScrollbars.tsx @@ -34,6 +34,11 @@ export const NavigationScrollbars = React.forwardRef(function NavigationScrollba useEffect(() => { window.addEventListener('beforeunload', beforeunload); return () => window.removeEventListener('beforeunload', beforeunload); + // These lint rules are disabled for now because the react plugin for eslint does + // not understand that useEffectEvent should not be added to the dependency array. + // Enable these rules again when eslint can lint useEffectEvent properly. + // eslint-disable-next-line react-compiler/react-compiler + // eslint-disable-next-line react-hooks/exhaustive-deps }, []); const onMount = useEffectEvent(() => { @@ -53,6 +58,11 @@ export const NavigationScrollbars = React.forwardRef(function NavigationScrollba useLayoutEffect(() => { onMount(); return () => onUnmount(); + // These lint rules are disabled for now because the react plugin for eslint does + // not understand that useEffectEvent should not be added to the dependency array. + // Enable these rules again when eslint can lint useEffectEvent properly. + // eslint-disable-next-line react-compiler/react-compiler + // eslint-disable-next-line react-hooks/exhaustive-deps }, []); const handleScroll = useCallback( diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/ProblemReport.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/ProblemReport.tsx index 331d107676..83e6efb322 100644 --- a/desktop/packages/mullvad-vpn/src/renderer/components/ProblemReport.tsx +++ b/desktop/packages/mullvad-vpn/src/renderer/components/ProblemReport.tsx @@ -504,6 +504,11 @@ const ProblemReportContextProvider = ({ children }: { children: ReactNode }) => /** * Save the form whenever email or message gets updated */ + // These lint rules are disabled for now because the react plugin for eslint does + // not understand that useEffectEvent should not be added to the dependency array. + // Enable these rules again when eslint can lint useEffectEvent properly. + // eslint-disable-next-line react-compiler/react-compiler + // eslint-disable-next-line react-hooks/exhaustive-deps useEffect(() => onMount(email, message), [email, message]); const value: ProblemReportContextType = useMemo( diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/ProxyForm.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/ProxyForm.tsx index e8e47bf15d..0eda7027ca 100644 --- a/desktop/packages/mullvad-vpn/src/renderer/components/ProxyForm.tsx +++ b/desktop/packages/mullvad-vpn/src/renderer/components/ProxyForm.tsx @@ -292,6 +292,11 @@ function EditShadowsocks(props: EditProxyProps<ShadowsocksCustomProxy>) { ); // Report back to form component with the proxy values when all required values are set. + // These lint rules are disabled for now because the react plugin for eslint does + // not understand that useEffectEvent should not be added to the dependency array. + // Enable these rules again when eslint can lint useEffectEvent properly. + // eslint-disable-next-line react-compiler/react-compiler + // eslint-disable-next-line react-hooks/exhaustive-deps useEffect(() => onUpdate(ip, port, password, cipher), [ip, port, password, cipher]); return ( @@ -371,6 +376,11 @@ function EditSocks5Remote(props: EditProxyProps<Socks5RemoteCustomProxy>) { ); // Report back to form component with the proxy values when all required values are set. + // These lint rules are disabled for now because the react plugin for eslint does + // not understand that useEffectEvent should not be added to the dependency array. + // Enable these rules again when eslint can lint useEffectEvent properly. + // eslint-disable-next-line react-compiler/react-compiler + // eslint-disable-next-line react-hooks/exhaustive-deps useEffect(() => onUpdate(ip, port, username, password), [ip, port, username, password]); return ( @@ -467,6 +477,11 @@ function EditSocks5Local(props: EditProxyProps<Socks5LocalCustomProxy>) { useEffect( () => onUpdate(remoteIp, remotePort, localPort, remoteTransportProtocol), + // These lint rules are disabled for now because the react plugin for eslint does + // not understand that useEffectEvent should not be added to the dependency array. + // Enable these rules again when eslint can lint useEffectEvent properly. + // eslint-disable-next-line react-compiler/react-compiler + // eslint-disable-next-line react-hooks/exhaustive-deps [remoteIp, remotePort, localPort, remoteTransportProtocol], ); diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/SearchBar.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/SearchBar.tsx index edbcb6df97..fb896b95e0 100644 --- a/desktop/packages/mullvad-vpn/src/renderer/components/SearchBar.tsx +++ b/desktop/packages/mullvad-vpn/src/renderer/components/SearchBar.tsx @@ -86,6 +86,11 @@ export default function SearchBar(props: ISearchBarProps) { } }); + // These lint rules are disabled for now because the react plugin for eslint does + // not understand that useEffectEvent should not be added to the dependency array. + // Enable these rules again when eslint can lint useEffectEvent properly. + // eslint-disable-next-line react-compiler/react-compiler + // eslint-disable-next-line react-hooks/exhaustive-deps useEffect(() => focusInput(), []); return ( diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/SettingsImport.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/SettingsImport.tsx index 541e5cab44..f25e411cc3 100644 --- a/desktop/packages/mullvad-vpn/src/renderer/components/SettingsImport.tsx +++ b/desktop/packages/mullvad-vpn/src/renderer/components/SettingsImport.tsx @@ -100,6 +100,11 @@ export default function SettingsImport() { } }); + // These lint rules are disabled for now because the react plugin for eslint does + // not understand that useEffectEvent should not be added to the dependency array. + // Enable these rules again when eslint can lint useEffectEvent properly. + // eslint-disable-next-line react-compiler/react-compiler + // eslint-disable-next-line react-hooks/exhaustive-deps useEffect(() => void onMount(), []); return ( diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/SplitTunnelingSettings.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/SplitTunnelingSettings.tsx index 26fe69ab7c..d18f671b5f 100644 --- a/desktop/packages/mullvad-vpn/src/renderer/components/SplitTunnelingSettings.tsx +++ b/desktop/packages/mullvad-vpn/src/renderer/components/SplitTunnelingSettings.tsx @@ -126,6 +126,11 @@ function LinuxSplitTunnelingSettings(props: IPlatformSplitTunnelingSettingsProps }); }); + // These lint rules are disabled for now because the react plugin for eslint does + // not understand that useEffectEvent should not be added to the dependency array. + // Enable these rules again when eslint can lint useEffectEvent properly. + // eslint-disable-next-line react-compiler/react-compiler + // eslint-disable-next-line react-hooks/exhaustive-deps useEffect(() => void updateApplications(), []); const launchApplication = useCallback( @@ -367,6 +372,11 @@ export function SplitTunnelingSettings(props: IPlatformSplitTunnelingSettingsPro }); }); + // These lint rules are disabled for now because the react plugin for eslint does + // not understand that useEffectEvent should not be added to the dependency array. + // Enable these rules again when eslint can lint useEffectEvent properly. + // eslint-disable-next-line react-compiler/react-compiler + // eslint-disable-next-line react-hooks/exhaustive-deps useEffect(() => void onMount(), []); const filteredSplitApplications = useMemo( diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/cell/Input.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/cell/Input.tsx index e7f129ca73..c1d9405b4b 100644 --- a/desktop/packages/mullvad-vpn/src/renderer/components/cell/Input.tsx +++ b/desktop/packages/mullvad-vpn/src/renderer/components/cell/Input.tsx @@ -147,6 +147,11 @@ function InputWithRef(props: IInputProps, forwardedRef: React.Ref<HTMLInputEleme // then we want to update the value. useEffect(() => { handleInitialValueChange(props.initialValue); + // These lint rules are disabled for now because the react plugin for eslint does + // not understand that useEffectEvent should not be added to the dependency array. + // Enable these rules again when eslint can lint useEffectEvent properly. + // eslint-disable-next-line react-compiler/react-compiler + // eslint-disable-next-line react-hooks/exhaustive-deps }, [props.initialValue]); const valid = validateValue?.(value); @@ -373,6 +378,11 @@ export function RowInput(props: IRowInputProps) { useEffect(() => { focusOnMount(); + // These lint rules are disabled for now because the react plugin for eslint does + // not understand that useEffectEvent should not be added to the dependency array. + // Enable these rules again when eslint can lint useEffectEvent properly. + // eslint-disable-next-line react-compiler/react-compiler + // eslint-disable-next-line react-hooks/exhaustive-deps }, []); useEffect(() => { diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/cell/Section.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/cell/Section.tsx index a21a70c034..38cdbb6820 100644 --- a/desktop/packages/mullvad-vpn/src/renderer/components/cell/Section.tsx +++ b/desktop/packages/mullvad-vpn/src/renderer/components/cell/Section.tsx @@ -79,6 +79,11 @@ export function ExpandableSection(props: ExpandableSectionProps) { useEffect(() => { updateHistory(expanded); + // These lint rules are disabled for now because the react plugin for eslint does + // not understand that useEffectEvent should not be added to the dependency array. + // Enable these rules again when eslint can lint useEffectEvent properly. + // eslint-disable-next-line react-compiler/react-compiler + // eslint-disable-next-line react-hooks/exhaustive-deps }, [expanded]); const title = ( diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/cell/SettingsForm.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/cell/SettingsForm.tsx index 9a901d88d8..f986101e04 100644 --- a/desktop/packages/mullvad-vpn/src/renderer/components/cell/SettingsForm.tsx +++ b/desktop/packages/mullvad-vpn/src/renderer/components/cell/SettingsForm.tsx @@ -43,6 +43,11 @@ export function useSettingsFormSubmittableReporter() { useEffect(() => { // Remove from required fields if unmounted. return () => clearRequiredFields(); + // These lint rules are disabled for now because the react plugin for eslint does + // not understand that useEffectEvent should not be added to the dependency array. + // Enable these rules again when eslint can lint useEffectEvent properly. + // eslint-disable-next-line react-compiler/react-compiler + // eslint-disable-next-line react-hooks/exhaustive-deps }, []); return reportInputSubmittable; diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/cell/SettingsSelect.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/cell/SettingsSelect.tsx index 3f6ccf3297..9acecc0222 100644 --- a/desktop/packages/mullvad-vpn/src/renderer/components/cell/SettingsSelect.tsx +++ b/desktop/packages/mullvad-vpn/src/renderer/components/cell/SettingsSelect.tsx @@ -145,6 +145,11 @@ export function SettingsSelect<T extends string>(props: SettingsSelectProps<T>) // Update the parent when the value changes. useEffect(() => { updateEvent(value); + // These lint rules are disabled for now because the react plugin for eslint does + // not understand that useEffectEvent should not be added to the dependency array. + // Enable these rules again when eslint can lint useEffectEvent properly. + // eslint-disable-next-line react-compiler/react-compiler + // eslint-disable-next-line react-hooks/exhaustive-deps }, [value]); return ( diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/cell/SettingsTextInput.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/cell/SettingsTextInput.tsx index 73b7a55e4e..45ced44d66 100644 --- a/desktop/packages/mullvad-vpn/src/renderer/components/cell/SettingsTextInput.tsx +++ b/desktop/packages/mullvad-vpn/src/renderer/components/cell/SettingsTextInput.tsx @@ -119,6 +119,11 @@ function Input<T extends ValueTypes>(props: InputProps<T>) { // Report submittability to form context on load. useEffect(() => { updateReportSubmittable(); + // These lint rules are disabled for now because the react plugin for eslint does + // not understand that useEffectEvent should not be added to the dependency array. + // Enable these rules again when eslint can lint useEffectEvent properly. + // eslint-disable-next-line react-compiler/react-compiler + // eslint-disable-next-line react-hooks/exhaustive-deps }, []); return ( diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/select-location/RelayListContext.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/select-location/RelayListContext.tsx index 0c093af313..89f9edaee5 100644 --- a/desktop/packages/mullvad-vpn/src/renderer/components/select-location/RelayListContext.tsx +++ b/desktop/packages/mullvad-vpn/src/renderer/components/select-location/RelayListContext.tsx @@ -320,6 +320,11 @@ function useExpandedLocations(filteredLocations: Array<IRelayLocationCountryRedu ); // Expand locations when filters are changed + // These lint rules are disabled for now because the react plugin for eslint does + // not understand that useEffectEvent should not be added to the dependency array. + // Enable these rules again when eslint can lint useEffectEvent properly. + // eslint-disable-next-line react-compiler/react-compiler + // eslint-disable-next-line react-hooks/exhaustive-deps useEffect(() => expandLocationsForSearch(filteredLocations), [filteredLocations]); return { diff --git a/desktop/packages/mullvad-vpn/src/renderer/lib/transition-hooks.ts b/desktop/packages/mullvad-vpn/src/renderer/lib/transition-hooks.ts index 592afc15a4..e48048c058 100644 --- a/desktop/packages/mullvad-vpn/src/renderer/lib/transition-hooks.ts +++ b/desktop/packages/mullvad-vpn/src/renderer/lib/transition-hooks.ts @@ -83,6 +83,11 @@ export function useViewTransitions(onTransition?: () => void): Location<Location return () => { unobserveHistory?.(); }; + // These lint rules are disabled for now because the react plugin for eslint does + // not understand that useEffectEvent should not be added to the dependency array. + // Enable these rules again when eslint can lint useEffectEvent properly. + // eslint-disable-next-line react-compiler/react-compiler + // eslint-disable-next-line react-hooks/exhaustive-deps }, [history]); return currentLocation; |
