Skip to content

Commit ce1f55b

Browse files
authored
Merge pull request #7991 from marmelab/fix-uselogout-does-not-empty-query-cache
Fix error after being logged out and logging in again
2 parents d13fd49 + 262b9f4 commit ce1f55b

File tree

3 files changed

+88
-14
lines changed

3 files changed

+88
-14
lines changed

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

+27-12
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { useState, useEffect } from 'react';
33
import expect from 'expect';
44
import { screen, render, waitFor } from '@testing-library/react';
55
import { unstable_HistoryRouter as HistoryRouter } from 'react-router-dom';
6+
import { QueryClientProvider, QueryClient } from 'react-query';
67
import { createMemoryHistory } from 'history';
78

89
import { useCheckAuth } from './useCheckAuth';
@@ -53,6 +54,8 @@ const authProvider: AuthProvider = {
5354
getPermissions: () => Promise.reject('not authenticated'),
5455
};
5556

57+
const queryClient = new QueryClient();
58+
5659
describe('useCheckAuth', () => {
5760
afterEach(() => {
5861
notify.mockClear();
@@ -63,7 +66,9 @@ describe('useCheckAuth', () => {
6366
render(
6467
<HistoryRouter history={history}>
6568
<AuthContext.Provider value={authProvider}>
66-
<TestComponent params={{ token: true }} />
69+
<QueryClientProvider client={queryClient}>
70+
<TestComponent params={{ token: true }} />
71+
</QueryClientProvider>
6772
</AuthContext.Provider>
6873
</HistoryRouter>
6974
);
@@ -79,7 +84,9 @@ describe('useCheckAuth', () => {
7984
render(
8085
<HistoryRouter history={history}>
8186
<AuthContext.Provider value={authProvider}>
82-
<TestComponent params={{ token: false }} />
87+
<QueryClientProvider client={queryClient}>
88+
<TestComponent params={{ token: false }} />
89+
</QueryClientProvider>
8390
</AuthContext.Provider>
8491
</HistoryRouter>
8592
);
@@ -95,10 +102,12 @@ describe('useCheckAuth', () => {
95102
render(
96103
<HistoryRouter history={history}>
97104
<AuthContext.Provider value={authProvider}>
98-
<TestComponent
99-
params={{ token: false }}
100-
logoutOnFailure={false}
101-
/>
105+
<QueryClientProvider client={queryClient}>
106+
<TestComponent
107+
params={{ token: false }}
108+
logoutOnFailure={false}
109+
/>
110+
</QueryClientProvider>
102111
</AuthContext.Provider>
103112
</HistoryRouter>
104113
);
@@ -114,10 +123,12 @@ describe('useCheckAuth', () => {
114123
render(
115124
<HistoryRouter history={history}>
116125
<AuthContext.Provider value={authProvider}>
117-
<TestComponent
118-
params={{ token: false }}
119-
disableNotification
120-
/>
126+
<QueryClientProvider client={queryClient}>
127+
<TestComponent
128+
params={{ token: false }}
129+
disableNotification
130+
/>
131+
</QueryClientProvider>
121132
</AuthContext.Provider>
122133
</HistoryRouter>
123134
);
@@ -138,7 +149,9 @@ describe('useCheckAuth', () => {
138149
checkAuth: () => Promise.reject({ message: false }),
139150
}}
140151
>
141-
<TestComponent />
152+
<QueryClientProvider client={queryClient}>
153+
<TestComponent />
154+
</QueryClientProvider>
142155
</AuthContext.Provider>
143156
</HistoryRouter>
144157
);
@@ -155,7 +168,9 @@ describe('useCheckAuth', () => {
155168
<HistoryRouter history={history}>
156169
<BasenameContextProvider basename="/foo">
157170
<AuthContext.Provider value={authProvider}>
158-
<TestComponent params={{ token: false }} />
171+
<QueryClientProvider client={queryClient}>
172+
<TestComponent params={{ token: false }} />
173+
</QueryClientProvider>
159174
</AuthContext.Provider>
160175
</BasenameContextProvider>
161176
</HistoryRouter>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
import * as React from 'react';
2+
import { render, fireEvent, screen } from '@testing-library/react';
3+
import { MemoryRouter, Routes, Route } from 'react-router-dom';
4+
import { QueryClient } from 'react-query';
5+
import expect from 'expect';
6+
7+
import { useGetOne } from '../dataProvider';
8+
import useLogout from './useLogout';
9+
import { CoreAdminContext } from '../core/CoreAdminContext';
10+
11+
describe('useLogout', () => {
12+
it('should clear the QueryClient cache', async () => {
13+
const LogoutButton = () => {
14+
const logout = useLogout();
15+
return <button onClick={logout}>Logout</button>;
16+
};
17+
const dataProvider = {
18+
getOne: () => Promise.resolve({ data: { id: 1, title: 'foo' } }),
19+
} as any;
20+
const queryClient = new QueryClient();
21+
const Content = () => {
22+
const { data } = useGetOne('posts', { id: 1 });
23+
return <div>{data?.title}</div>;
24+
};
25+
const Login = () => <div>Login</div>;
26+
render(
27+
<MemoryRouter>
28+
<CoreAdminContext
29+
dataProvider={dataProvider}
30+
queryClient={queryClient}
31+
>
32+
<Routes>
33+
<Route path="/" element={<Content />} />
34+
<Route path="/login" element={<Login />} />
35+
</Routes>
36+
37+
<LogoutButton />
38+
</CoreAdminContext>
39+
</MemoryRouter>
40+
);
41+
await screen.findByText('foo');
42+
expect(
43+
queryClient.getQueryData(['posts', 'getOne', { id: '1' }])
44+
).toEqual({
45+
id: 1,
46+
title: 'foo',
47+
});
48+
fireEvent.click(screen.getByText('Logout'));
49+
await screen.findByText('Login');
50+
expect(
51+
queryClient.getQueryData(['posts', 'getOne', { id: '1' }])
52+
).toBeUndefined();
53+
});
54+
});

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

+7-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { useCallback, useEffect, useRef } from 'react';
22
import { useLocation, useNavigate, Path } from 'react-router-dom';
3+
import { useQueryClient } from 'react-query';
34

45
import useAuthProvider, { defaultAuthParams } from './useAuthProvider';
56
import { useResetStore } from '../store';
@@ -26,6 +27,7 @@ import { removeDoubleSlashes } from '../routing/useCreatePath';
2627
*/
2728
const useLogout = (): Logout => {
2829
const authProvider = useAuthProvider();
30+
const queryClient = useQueryClient();
2931
const resetStore = useResetStore();
3032
const navigate = useNavigate();
3133
// useNavigate forces rerenders on every navigation, even if we don't use the result
@@ -64,6 +66,7 @@ const useLogout = (): Logout => {
6466
authProvider.logout(params).then(redirectToFromProvider => {
6567
if (redirectToFromProvider === false) {
6668
resetStore();
69+
queryClient.clear();
6770
// do not redirect
6871
return;
6972
}
@@ -94,10 +97,11 @@ const useLogout = (): Logout => {
9497
}
9598
navigateRef.current(newLocation, newLocationOptions);
9699
resetStore();
100+
queryClient.clear();
97101

98102
return redirectToFromProvider;
99103
}),
100-
[authProvider, resetStore, loginUrl]
104+
[authProvider, resetStore, loginUrl, queryClient]
101105
);
102106

103107
const logoutWithoutProvider = useCallback(
@@ -113,9 +117,10 @@ const useLogout = (): Logout => {
113117
}
114118
);
115119
resetStore();
120+
queryClient.clear();
116121
return Promise.resolve();
117122
},
118-
[resetStore, location, navigate, loginUrl]
123+
[resetStore, location, navigate, loginUrl, queryClient]
119124
);
120125

121126
return authProvider ? logout : logoutWithoutProvider;

0 commit comments

Comments
 (0)