From 3c37db708dd8091ebc0af277f4c0e6ba89cfd9ea Mon Sep 17 00:00:00 2001 From: Gao Sun Date: Tue, 25 Jul 2023 15:13:58 +0800 Subject: [PATCH] fix(console): use SWR for user endpoint --- .../src/containers/TenantAccess/index.tsx | 13 ++++++-- .../console/src/contexts/AppDataProvider.tsx | 32 ++++++++----------- 2 files changed, 23 insertions(+), 22 deletions(-) diff --git a/packages/console/src/containers/TenantAccess/index.tsx b/packages/console/src/containers/TenantAccess/index.tsx index be6ec0795..43a8d4174 100644 --- a/packages/console/src/containers/TenantAccess/index.tsx +++ b/packages/console/src/containers/TenantAccess/index.tsx @@ -56,10 +56,17 @@ export default function TenantAccess() { /** * The official cache clean method, see {@link https://github.com/vercel/swr/issues/1887#issuecomment-1171269211 | this comment}. * - * We need to exclude the `me` key because it's not tenant-aware. If don't, we - * need to manually revalidate the `me` key to make console work again. + * Exceptions: + * - Exclude the `me` key because it's not tenant-aware. If don't, we need to manually + * revalidate the `me` key to make console work again. + * - Exclude keys that include `/.well-known/` because they are usually static and + * should not be revalidated. */ - void mutate((key) => key !== 'me', undefined, { rollbackOnError: false, throwOnError: false }); + void mutate( + (key) => typeof key !== 'string' || (key !== 'me' && !key.includes('/.well-known/')), + undefined, + { rollbackOnError: false, throwOnError: false } + ); }, [mutate, currentTenantId]); useEffect(() => { diff --git a/packages/console/src/contexts/AppDataProvider.tsx b/packages/console/src/contexts/AppDataProvider.tsx index 1fe504ae9..61ec0b635 100644 --- a/packages/console/src/contexts/AppDataProvider.tsx +++ b/packages/console/src/contexts/AppDataProvider.tsx @@ -1,6 +1,7 @@ import ky from 'ky'; import type { ReactNode } from 'react'; -import { useContext, useMemo, useEffect, createContext, useState } from 'react'; +import { useContext, useMemo, createContext } from 'react'; +import useSWRImmutable from 'swr/immutable'; import { adminTenantEndpoint } from '@/consts'; @@ -23,9 +24,18 @@ export const AppDataContext = createContext({}); /** The context provider for the global app data. */ function AppDataProvider({ children }: Props) { - const [userEndpoint, setUserEndpoint] = useState(); - const [isLoading, setIsLoading] = useState(false); const { currentTenantId } = useContext(TenantsContext); + + const { data: userEndpoint } = useSWRImmutable( + `api/.well-known/endpoints/${currentTenantId}`, + async (pathname) => { + const { user } = await ky + .get(new URL(pathname, adminTenantEndpoint)) + .json<{ user: string }>(); + return new URL(user); + } + ); + const memorizedContext = useMemo( () => ({ @@ -34,22 +44,6 @@ function AppDataProvider({ children }: Props) { [userEndpoint] ); - useEffect(() => { - const getEndpoint = async () => { - setIsLoading(true); - const { user } = await ky - .get(new URL(`api/.well-known/endpoints/${currentTenantId}`, adminTenantEndpoint)) - .json<{ user: string }>(); - setUserEndpoint(new URL(user)); - }; - - if (!currentTenantId || isLoading || userEndpoint) { - return; - } - - void getEndpoint(); - }, [currentTenantId, isLoading, userEndpoint]); - return {children}; }