From e0935d7faa1ef1def61dde75152de8d769bb02a0 Mon Sep 17 00:00:00 2001 From: Zoe Roux Date: Sun, 19 May 2024 18:20:02 +0200 Subject: [PATCH] Fix accounts infinite rerender loop --- front/packages/models/src/accounts.tsx | 29 +++++++++++++------ front/packages/primitives/src/menu.tsx | 2 +- .../packages/primitives/src/themes/theme.tsx | 9 ++---- 3 files changed, 23 insertions(+), 17 deletions(-) diff --git a/front/packages/models/src/accounts.tsx b/front/packages/models/src/accounts.tsx index 5dbb98d4..aa4555a8 100644 --- a/front/packages/models/src/accounts.tsx +++ b/front/packages/models/src/accounts.tsx @@ -133,19 +133,31 @@ export const AccountProvider = ({ setApiUrl(selected?.apiUrl ?? defaultApiUrl); }, [selected, setApiUrl]); - const user = useFetch({ + const { + isSuccess: userIsSuccess, + isError: userIsError, + isLoading: userIsLoading, + isPlaceholderData: userIsPlaceholder, + data: user, + error: userError, + } = useFetch({ path: ["auth", "me"], parser: UserP, placeholderData: selected as User, enabled: !!selected, }); + // Use a ref here because we don't want the effect to trigger when the selected + // value has changed, only when the fetch result changed + // If we trigger the effect when the selected value change, we enter an infinite render loop + const selectedRef = useRef(selected); + selectedRef.current = selected; useEffect(() => { - if (!selected || !user.isSuccess || user.isPlaceholderData) return; + if (!selectedRef.current || !userIsSuccess || userIsPlaceholder) return; // The id is different when user is stale data, we need to wait for the use effect to invalidate the query. - if (user.data.id !== selected.id) return; - const nUser = { ...selected, ...user.data }; - if (!Object.is(selected, nUser)) updateAccount(nUser.id, nUser); - }, [selected, user]); + if (user.id !== selectedRef.current.id) return; + const nUser = { ...selectedRef.current, ...user }; + updateAccount(nUser.id, nUser); + }, [user]); const queryClient = useQueryClient(); const oldSelected = useRef<{ id: string; token: string } | null>( @@ -154,7 +166,6 @@ export const AccountProvider = ({ const [permissionError, setPermissionError] = useState(null); - const userIsError = user.isError; useEffect(() => { // if the user change account (or connect/disconnect), reset query cache. if ( @@ -180,8 +191,8 @@ export const AccountProvider = ({ { queryClient.invalidateQueries({ queryKey: ["auth", "me"] }); }, diff --git a/front/packages/primitives/src/menu.tsx b/front/packages/primitives/src/menu.tsx index 9e255dba..90f05320 100644 --- a/front/packages/primitives/src/menu.tsx +++ b/front/packages/primitives/src/menu.tsx @@ -68,7 +68,7 @@ const Menu = ({ const [isOpen, setOpen] = outerOpen !== undefined && outerSetOpen ? [outerOpen, outerSetOpen] : useState(false); - // deos the same as a useMemo but for props. + // does the same as a useMemo but for props. const memoRef = useRef({ onMenuOpen, onMenuClose }); memoRef.current = { onMenuOpen, onMenuClose }; useEffect(() => { diff --git a/front/packages/primitives/src/themes/theme.tsx b/front/packages/primitives/src/themes/theme.tsx index b31d1eea..dfe6447b 100644 --- a/front/packages/primitives/src/themes/theme.tsx +++ b/front/packages/primitives/src/themes/theme.tsx @@ -20,19 +20,14 @@ import type { Property } from "csstype"; import type { ReactNode } from "react"; -import { Platform } from "react-native"; +import { Platform, type TextStyle } from "react-native"; import { type Theme, ThemeProvider, useAutomaticTheme } from "yoshiki"; import "yoshiki"; import { useTheme, useYoshiki } from "yoshiki/native"; import "yoshiki/native"; import { catppuccin } from "./catppuccin"; -type FontList = Partial< - Record< - "normal" | "bold" | "100" | "200" | "300" | "400" | "500" | "600" | "700" | "800" | "900", - string - > ->; +type FontList = Partial, string>>; type Mode = { mode: "light" | "dark" | "auto";