Skip to content

Commit 6ef98e7

Browse files
authored
Merge pull request #10486 from marmelab/fix/useHandleCallback_compatible_StrictMode
Make useHandleCallback compatible with StrictMode
2 parents 107db17 + 5cbe2f8 commit 6ef98e7

File tree

2 files changed

+37
-6
lines changed

2 files changed

+37
-6
lines changed

packages/ra-core/src/auth/useHandleAuthCallback.spec.tsx

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,4 +160,28 @@ describe('useHandleAuthCallback', () => {
160160
expect(abort).toHaveBeenCalled();
161161
});
162162
});
163+
164+
it('should only call handleCallback once when the component is rendered', async () => {
165+
const handleCallback = jest.spyOn(authProvider, 'handleCallback');
166+
render(
167+
<React.StrictMode>
168+
<TestMemoryRouter initialEntries={['/auth-callback']}>
169+
<AuthContext.Provider value={authProvider}>
170+
<QueryClientProvider client={new QueryClient()}>
171+
<Routes>
172+
<Route path="/" element={<div>Home</div>} />
173+
<Route
174+
path="/auth-callback"
175+
element={<TestComponent />}
176+
/>
177+
</Routes>
178+
</QueryClientProvider>
179+
</AuthContext.Provider>
180+
</TestMemoryRouter>
181+
</React.StrictMode>
182+
);
183+
184+
await screen.findByText('Home');
185+
expect(handleCallback).toHaveBeenCalledTimes(1);
186+
});
163187
});

packages/ra-core/src/auth/useHandleAuthCallback.ts

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,15 +24,22 @@ export const useHandleAuthCallback = (
2424
const nextSearch = locationState && locationState.nextSearch;
2525
const defaultRedirectUrl = nextPathName ? nextPathName + nextSearch : '/';
2626
const { onSuccess, onError, onSettled, ...queryOptions } = options ?? {};
27+
let handleCallbackPromise: Promise<void> | null;
2728

2829
const queryResult = useQuery({
2930
queryKey: ['auth', 'handleCallback'],
30-
queryFn: ({ signal }) =>
31-
authProvider && typeof authProvider.handleCallback === 'function'
32-
? authProvider
33-
.handleCallback({ signal })
34-
.then(result => result ?? null)
35-
: Promise.resolve(),
31+
queryFn: ({ signal }) => {
32+
if (!handleCallbackPromise) {
33+
handleCallbackPromise =
34+
authProvider &&
35+
typeof authProvider.handleCallback === 'function'
36+
? authProvider
37+
.handleCallback({ signal })
38+
.then(result => result ?? null)
39+
: Promise.resolve();
40+
}
41+
return handleCallbackPromise;
42+
},
3643
retry: false,
3744
...queryOptions,
3845
});

0 commit comments

Comments
 (0)