Skip to content

Commit 003efec

Browse files
authored
Fix react query cache not being cleared when switching budgets (#6953)
* Fix react query cache not being cleared when switching budgets * React does not want to export function from src/index * Release note
1 parent 155e4df commit 003efec

File tree

7 files changed

+71
-48
lines changed

7 files changed

+71
-48
lines changed

packages/desktop-client/src/budgetfiles/budgetfilesSlice.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -100,10 +100,11 @@ export const loadBudget = createAppAsyncThunk(
100100

101101
export const closeBudget = createAppAsyncThunk(
102102
`${sliceName}/closeBudget`,
103-
async (_, { dispatch, getState }) => {
103+
async (_, { dispatch, getState, extra: { queryClient } }) => {
104104
const prefs = getState().prefs.local;
105105
if (prefs && prefs.id) {
106106
await dispatch(resetApp());
107+
queryClient.clear();
107108
await dispatch(setAppState({ loadingText: t('Closing...') }));
108109
await send('close-budget');
109110
await dispatch(setAppState({ loadingText: null }));
@@ -116,10 +117,11 @@ export const closeBudget = createAppAsyncThunk(
116117

117118
export const closeBudgetUI = createAppAsyncThunk(
118119
`${sliceName}/closeBudgetUI`,
119-
async (_, { dispatch, getState }) => {
120+
async (_, { dispatch, getState, extra: { queryClient } }) => {
120121
const prefs = getState().prefs.local;
121122
if (prefs && prefs.id) {
122123
await dispatch(resetApp());
124+
queryClient.clear();
123125
}
124126
},
125127
);

packages/desktop-client/src/components/reports/Change.test.tsx

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,18 @@
11
import React from 'react';
2-
import { Provider } from 'react-redux';
32

43
import { theme } from '@actual-app/components/theme';
54
import { render, screen } from '@testing-library/react';
65

76
import { Change } from './Change';
87

9-
import { configureAppStore } from '@desktop-client/redux/store';
10-
11-
const store = configureAppStore();
8+
import { TestProviders } from '@desktop-client/mocks';
129

1310
describe('Change', () => {
1411
it('renders a positive amount with a plus sign and positive color', () => {
1512
render(
16-
<Provider store={store}>
13+
<TestProviders>
1714
<Change amount={12345} />
18-
</Provider>,
15+
</TestProviders>,
1916
);
2017
const el = screen.getByText('+123.45');
2118
expect(el).toBeInTheDocument();
@@ -24,9 +21,9 @@ describe('Change', () => {
2421

2522
it('renders zero with a plus sign and neutral color', () => {
2623
render(
27-
<Provider store={store}>
24+
<TestProviders>
2825
<Change amount={0} />
29-
</Provider>,
26+
</TestProviders>,
3027
);
3128
const el = screen.getByText('+0.00');
3229
expect(el).toBeInTheDocument();
@@ -35,9 +32,9 @@ describe('Change', () => {
3532

3633
it('renders a negative amount with a minus sign and negative color', () => {
3734
render(
38-
<Provider store={store}>
35+
<TestProviders>
3936
<Change amount={-9876} />
40-
</Provider>,
37+
</TestProviders>,
4138
);
4239
const el = screen.getByText('-98.76');
4340
expect(el).toBeInTheDocument();
@@ -46,9 +43,9 @@ describe('Change', () => {
4643

4744
it('merges custom style prop', () => {
4845
render(
49-
<Provider store={store}>
46+
<TestProviders>
5047
<Change amount={1000} style={{ fontWeight: 'bold' }} />
51-
</Provider>,
48+
</TestProviders>,
5249
);
5350
const el = screen.getByText('+10.00');
5451
expect(el).toHaveStyle('font-weight: bold');

packages/desktop-client/src/index.tsx

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ import * as usersSlice from './users/usersSlice';
3535
const queryClient = new QueryClient();
3636
window.__TANSTACK_QUERY_CLIENT__ = queryClient;
3737

38-
const store = configureAppStore();
38+
const store = configureAppStore({ queryClient });
3939

4040
const boundActions = bindActionCreators(
4141
{
@@ -90,15 +90,15 @@ window.$q = q;
9090
const container = document.getElementById('root');
9191
const root = createRoot(container);
9292
root.render(
93-
<Provider store={store}>
94-
<ServerProvider>
95-
<AuthProvider>
96-
<QueryClientProvider client={queryClient}>
93+
<QueryClientProvider client={queryClient}>
94+
<Provider store={store}>
95+
<ServerProvider>
96+
<AuthProvider>
9797
<App />
98-
</QueryClientProvider>
99-
</AuthProvider>
100-
</ServerProvider>
101-
</Provider>,
98+
</AuthProvider>
99+
</ServerProvider>
100+
</Provider>
101+
</QueryClientProvider>,
102102
);
103103

104104
declare global {

packages/desktop-client/src/mocks.tsx

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,22 +4,37 @@ import { Provider } from 'react-redux';
44
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
55

66
import { configureAppStore } from './redux/store';
7-
import type { AppStore } from './redux/store';
87

9-
let mockQueryClient = new QueryClient();
10-
let mockStore: AppStore = configureAppStore();
8+
export function createTestQueryClient() {
9+
return new QueryClient({
10+
defaultOptions: {
11+
queries: {
12+
retry: false,
13+
},
14+
},
15+
});
16+
}
17+
18+
export function configureTestAppStore(
19+
...args: Parameters<typeof configureAppStore>
20+
) {
21+
return configureAppStore(...args);
22+
}
23+
24+
let testQueryClient = createTestQueryClient();
25+
let testStore = configureTestAppStore({
26+
queryClient: testQueryClient,
27+
});
1128

1229
export function resetTestProviders() {
13-
mockQueryClient = new QueryClient();
14-
mockStore = configureAppStore();
30+
testQueryClient = createTestQueryClient();
31+
testStore = configureTestAppStore({ queryClient: testQueryClient });
1532
}
1633

1734
export function TestProviders({ children }: { children: ReactNode }) {
1835
return (
19-
<Provider store={mockStore}>
20-
<QueryClientProvider client={mockQueryClient}>
21-
{children}
22-
</QueryClientProvider>
23-
</Provider>
36+
<QueryClientProvider client={testQueryClient}>
37+
<Provider store={testStore}>{children}</Provider>
38+
</QueryClientProvider>
2439
);
2540
}

packages/desktop-client/src/redux/index.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,12 @@ import {
77

88
import { createAsyncThunk } from '@reduxjs/toolkit';
99

10-
import type { AppDispatch, AppStore, RootState } from './store';
10+
import type { AppDispatch, AppStore, ExtraArguments, RootState } from './store';
1111

1212
export const createAppAsyncThunk = createAsyncThunk.withTypes<{
1313
state: RootState;
1414
dispatch: AppDispatch;
15+
extra: ExtraArguments;
1516
}>();
1617

1718
export const useStore = useReduxStore.withTypes<AppStore>();

packages/desktop-client/src/redux/store.ts

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import {
44
createListenerMiddleware,
55
isRejected,
66
} from '@reduxjs/toolkit';
7+
import type { QueryClient } from '@tanstack/react-query';
78

89
import {
910
name as accountsSliceName,
@@ -77,27 +78,28 @@ notifyOnRejectedActionsMiddleware.startListening({
7778
},
7879
});
7980

80-
export const store = configureStore({
81-
reducer: rootReducer,
82-
middleware: getDefaultMiddleware =>
83-
getDefaultMiddleware({
84-
// TODO: Fix this in a separate PR. Remove non-serializable states in the store.
85-
serializableCheck: false,
86-
}).prepend(notifyOnRejectedActionsMiddleware.middleware),
87-
});
88-
89-
export function configureAppStore() {
81+
export function configureAppStore({
82+
queryClient,
83+
}: {
84+
queryClient: QueryClient;
85+
}) {
9086
return configureStore({
9187
reducer: rootReducer,
9288
middleware: getDefaultMiddleware =>
9389
getDefaultMiddleware({
9490
// TODO: Fix this in a separate PR. Remove non-serializable states in the store.
9591
serializableCheck: false,
92+
thunk: {
93+
extraArgument: { queryClient } as ExtraArguments,
94+
},
9695
}).prepend(notifyOnRejectedActionsMiddleware.middleware),
9796
});
9897
}
9998

100-
export type AppStore = typeof store;
101-
export type RootState = ReturnType<typeof store.getState>;
102-
export type AppDispatch = typeof store.dispatch;
103-
export type GetRootState = typeof store.getState;
99+
export type AppStore = ReturnType<typeof configureAppStore>;
100+
export type RootState = ReturnType<AppStore['getState']>;
101+
export type AppDispatch = AppStore['dispatch'];
102+
export type GetRootState = AppStore['getState'];
103+
export type ExtraArguments = {
104+
queryClient: QueryClient;
105+
};

upcoming-release-notes/6953.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
category: Bugfixes
3+
authors: [joel-jeremy]
4+
---
5+
6+
Fix react query cache not being cleared when switching budgets

0 commit comments

Comments
 (0)