diff --git a/packages/ra-core/src/auth/useHandleAuthCallback.spec.tsx b/packages/ra-core/src/auth/useHandleAuthCallback.spec.tsx
index 1ba624e777..7452fa26df 100644
--- a/packages/ra-core/src/auth/useHandleAuthCallback.spec.tsx
+++ b/packages/ra-core/src/auth/useHandleAuthCallback.spec.tsx
@@ -160,4 +160,28 @@ describe('useHandleAuthCallback', () => {
expect(abort).toHaveBeenCalled();
});
});
+
+ it('should only call handleCallback once when the component is rendered', async () => {
+ const handleCallback = jest.spyOn(authProvider, 'handleCallback');
+ render(
+
+
+
+
+
+ Home} />
+ }
+ />
+
+
+
+
+
+ );
+
+ await screen.findByText('Home');
+ expect(handleCallback).toHaveBeenCalledTimes(1);
+ });
});
diff --git a/packages/ra-core/src/auth/useHandleAuthCallback.ts b/packages/ra-core/src/auth/useHandleAuthCallback.ts
index 39c6df2bfe..b55a492f83 100644
--- a/packages/ra-core/src/auth/useHandleAuthCallback.ts
+++ b/packages/ra-core/src/auth/useHandleAuthCallback.ts
@@ -24,15 +24,38 @@ export const useHandleAuthCallback = (
const nextSearch = locationState && locationState.nextSearch;
const defaultRedirectUrl = nextPathName ? nextPathName + nextSearch : '/';
const { onSuccess, onError, onSettled, ...queryOptions } = options ?? {};
+ let handleCallbackPromise: Promise | null;
const queryResult = useQuery({
queryKey: ['auth', 'handleCallback'],
- queryFn: ({ signal }) =>
- authProvider && typeof authProvider.handleCallback === 'function'
- ? authProvider
- .handleCallback({ signal })
- .then(result => result ?? null)
- : Promise.resolve(),
+ queryFn: ({ signal }) => {
+ console.log('queryFn', handleCallbackPromise);
+ if (!handleCallbackPromise) {
+ handleCallbackPromise = new Promise(async (resolve, reject) => {
+ if (authProvider) {
+ if (typeof authProvider.handleCallback === 'function') {
+ try {
+ const result =
+ await authProvider.handleCallback({
+ signal,
+ });
+ return resolve(result ?? null);
+ } catch (error) {
+ return reject({
+ redirectTo: false,
+ message: error.message,
+ });
+ }
+ }
+ return resolve();
+ }
+ return reject({
+ message: 'Failed to handle login callback.',
+ });
+ });
+ }
+ return handleCallbackPromise;
+ },
retry: false,
...queryOptions,
});