From 7687c31c27c1474ef97357bbff8a178a4a28ad53 Mon Sep 17 00:00:00 2001 From: simeng-li Date: Tue, 20 Aug 2024 14:25:40 +0800 Subject: [PATCH] feat: add isInitialized flag (#30) * feat: add isInitialized flag add isInitialized flag * fix: update workflow update ci workflow --- .github/workflows/commitlint.yml | 4 ++-- .github/workflows/main.yml | 2 +- packages/rn-sample/App.tsx | 6 +++--- packages/rn/package.json | 2 +- packages/rn/src/context.ts | 8 ++++++++ packages/rn/src/hooks.ts | 8 ++++++-- packages/rn/src/provider.tsx | 8 ++++++-- 7 files changed, 27 insertions(+), 11 deletions(-) diff --git a/.github/workflows/commitlint.yml b/.github/workflows/commitlint.yml index 9fd3ff9..c403696 100644 --- a/.github/workflows/commitlint.yml +++ b/.github/workflows/commitlint.yml @@ -4,7 +4,7 @@ on: pull_request: types: [opened, edited, synchronize, reopened] -concurrency: +concurrency: group: commitlint-${{ github.ref }} cancel-in-progress: true @@ -17,7 +17,7 @@ jobs: fetch-depth: 0 - name: Setup Node and pnpm - uses: silverhand-io/actions-node-pnpm-run-steps@v4 + uses: silverhand-io/actions-node-pnpm-run-steps@v5 with: pnpm-version: 9 diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 75a23d1..b2ff10c 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -19,7 +19,7 @@ jobs: - uses: actions/checkout@v4 - name: Setup Node and pnpm - uses: silverhand-io/actions-node-pnpm-run-steps@v4 + uses: silverhand-io/actions-node-pnpm-run-steps@v5 with: pnpm-version: 9 diff --git a/packages/rn-sample/App.tsx b/packages/rn-sample/App.tsx index f689f89..79a94b9 100644 --- a/packages/rn-sample/App.tsx +++ b/packages/rn-sample/App.tsx @@ -9,7 +9,7 @@ const endpoint = 'https://'; const appId = ''; const Content = () => { - const { signIn, signOut, client, isAuthenticated, getIdTokenClaims } = useLogto(); + const { signIn, signOut, client, isAuthenticated, isInitialized, getIdTokenClaims } = useLogto(); const [claims, setClaims] = useState(); useEffect(() => { @@ -17,10 +17,10 @@ const Content = () => { setClaims(await getIdTokenClaims()); }; - if (isAuthenticated) { + if (isInitialized && isAuthenticated) { void get(); } - }, [isAuthenticated, getIdTokenClaims]); + }, [isAuthenticated, getIdTokenClaims, isInitialized]); return ( diff --git a/packages/rn/package.json b/packages/rn/package.json index 987fd4a..f4e09bc 100644 --- a/packages/rn/package.json +++ b/packages/rn/package.json @@ -3,7 +3,7 @@ "publishConfig": { "access": "public" }, - "version": "0.2.0", + "version": "0.3.0", "type": "module", "main": "./lib/index.js", "types": "./lib/index.d.ts", diff --git a/packages/rn/src/context.ts b/packages/rn/src/context.ts index a146ea9..13bc39c 100644 --- a/packages/rn/src/context.ts +++ b/packages/rn/src/context.ts @@ -4,6 +4,13 @@ import type { LogtoClient } from './client'; export type LogtoContextProps = { client: LogtoClient; + /** + * Indicates if the client is initialized. + * + * - `true`: The client is initialized, and the authentication state is fetched. + * - `false`: The client is not initialized. + */ + isInitialized: boolean; isAuthenticated: boolean; setIsAuthenticated: React.Dispatch>; }; @@ -15,6 +22,7 @@ export const throwContextError = (): never => { export const LogtoContext = createContext({ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion client: undefined!, + isInitialized: false, isAuthenticated: false, setIsAuthenticated: throwContextError, }); diff --git a/packages/rn/src/hooks.ts b/packages/rn/src/hooks.ts index aad4c0d..7ce958b 100644 --- a/packages/rn/src/hooks.ts +++ b/packages/rn/src/hooks.ts @@ -11,7 +11,7 @@ import { LogtoContext } from './context'; * `LogtoProvider` component to wrap the root component of the app. */ export const useLogto = () => { - const { client, isAuthenticated, setIsAuthenticated } = useContext(LogtoContext); + const { client, isAuthenticated, setIsAuthenticated, isInitialized } = useContext(LogtoContext); useEffect(() => { // This is required to handle the redirect from the browser on a web-based expo app @@ -45,6 +45,10 @@ export const useLogto = () => { * tokens are valid. */ isAuthenticated, + /** + * Indicates if the client is initialized and the authentication state is retrieved from the storage. + */ + isInitialized, /** @see {@link LogtoClient.getRefreshToken} */ getRefreshToken: client.getRefreshToken.bind(client), /** @see {@link LogtoClient.getAccessToken} */ @@ -66,7 +70,7 @@ export const useLogto = () => { /** @see {@link LogtoClient.fetchUserInfo} */ fetchUserInfo: client.fetchUserInfo.bind(client), }), - [client, isAuthenticated, signIn, signOut] + [client, isAuthenticated, isInitialized, signIn, signOut] ); return memorized; diff --git a/packages/rn/src/provider.tsx b/packages/rn/src/provider.tsx index d324648..5c12f71 100644 --- a/packages/rn/src/provider.tsx +++ b/packages/rn/src/provider.tsx @@ -16,12 +16,15 @@ export type LogtoProviderProps = { export const LogtoProvider = ({ config, children }: LogtoProviderProps) => { const memorizedLogtoClient = useMemo(() => new LogtoClient(config), [config]); const [isAuthenticated, setIsAuthenticated] = useState(false); + const [isInitialized, setIsInitialized] = useState(false); useEffect(() => { (async () => { const isAuthenticated = await memorizedLogtoClient.isAuthenticated(); - setIsAuthenticated(isAuthenticated); + + // Mark the client as initialized. + setIsInitialized(true); })(); }, [memorizedLogtoClient]); @@ -29,9 +32,10 @@ export const LogtoProvider = ({ config, children }: LogtoProviderProps) => { () => ({ client: memorizedLogtoClient, isAuthenticated, + isInitialized, setIsAuthenticated, }), - [memorizedLogtoClient, isAuthenticated] + [memorizedLogtoClient, isAuthenticated, isInitialized] ); return {children};