Skip to content

Commit 7228a72

Browse files
feat: context sharing (#188)
1 parent 33acbf6 commit 7228a72

File tree

6 files changed

+69
-8
lines changed

6 files changed

+69
-8
lines changed

examples/multi-page/index.html

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,10 @@
55
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
66
<title>Vue-query example</title>
77
</head>
8-
<body>
8+
<body style="display:flex;">
99
<div id="app"></div>
10+
<br />
11+
<div id="app2"></div>
1012
<script type="module" src="/src/main.ts"></script>
1113
</body>
1214
</html>

examples/multi-page/src/Page.vue

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,6 @@ export default defineComponent({
3030
cacheTime: 4000,
3131
}
3232
);
33-
useQuery("todos2", todoFetcher);
34-
useQuery("todos3", todoFetcher);
3533
3634
return { isLoading, isError, isFetching, data, error, refetch };
3735
},

examples/multi-page/src/main.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
11
import { createApp } from "vue";
2-
import { VueQueryPlugin } from "vue-query";
2+
import { VueQueryPlugin, VueQueryPluginOptions } from "vue-query";
33

44
import App from "./App.vue";
55

6-
createApp(App).use(VueQueryPlugin).mount("#app");
6+
createApp(App)
7+
.use(VueQueryPlugin, { contextSharing: true } as VueQueryPluginOptions)
8+
.mount("#app");
9+
// Second app mounted here will share vue-query context with the first app - click refresh to refresh both apps state
10+
createApp(App)
11+
.use(VueQueryPlugin, { contextSharing: true } as VueQueryPluginOptions)
12+
.mount("#app2");

jest.config.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ const config: Config.InitialOptions = {
99
moduleNameMapper: {
1010
"^vue-query": "<rootDir>/src/index.ts",
1111
},
12+
testEnvironment: "jsdom",
1213
testPathIgnorePatterns: ["test-utils.ts"],
1314
collectCoverage: true,
1415
collectCoverageFrom: [

src/vue/__tests__/vueQueryPlugin.test.ts

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ function getAppMock(withUnmountHook = false): TestApp {
3737
describe("VueQueryPlugin", () => {
3838
beforeEach(() => {
3939
jest.clearAllMocks();
40+
window.__VUE_QUERY_CONTEXT__ = undefined;
4041
});
4142

4243
describe("devtools", () => {
@@ -307,4 +308,34 @@ describe("VueQueryPlugin", () => {
307308
}
308309
);
309310
});
311+
312+
describe("when context sharing is enabled", () => {
313+
test("should create context if it does not exist", () => {
314+
const appMock = getAppMock();
315+
VueQueryPlugin.install?.(appMock, { contextSharing: true });
316+
317+
expect(window.__VUE_QUERY_CONTEXT__).toBeTruthy();
318+
});
319+
320+
test("should create context with options if it does not exist", () => {
321+
const appMock = getAppMock();
322+
VueQueryPlugin.install?.(appMock, {
323+
contextSharing: true,
324+
queryClientConfig: { defaultOptions: { queries: { staleTime: 5000 } } },
325+
});
326+
327+
expect(
328+
window.__VUE_QUERY_CONTEXT__?.getDefaultOptions().queries?.staleTime
329+
).toEqual(5000);
330+
});
331+
332+
test("should use existing context", () => {
333+
const customClient = { mount: jest.fn() } as unknown as QueryClient;
334+
window.__VUE_QUERY_CONTEXT__ = customClient;
335+
const appMock = getAppMock();
336+
VueQueryPlugin.install?.(appMock, { contextSharing: true });
337+
338+
expect(customClient.mount).toHaveBeenCalledTimes(1);
339+
});
340+
});
310341
});

src/vue/vueQueryPlugin.ts

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,12 @@ import { getClientKey } from "./utils";
66
import { setupDevtools } from "./devtools/devtools";
77
import { MaybeRefDeep } from "./types";
88

9+
declare global {
10+
interface Window {
11+
__VUE_QUERY_CONTEXT__?: QueryClient;
12+
}
13+
}
14+
915
export interface AdditionalClient {
1016
queryClient: QueryClient;
1117
queryClientKey: string;
@@ -15,12 +21,14 @@ interface ConfigOptions {
1521
queryClientConfig?: MaybeRefDeep<QueryClientConfig>;
1622
queryClientKey?: string;
1723
additionalClients?: AdditionalClient[];
24+
contextSharing?: boolean;
1825
}
1926

2027
interface ClientOptions {
2128
queryClient?: QueryClient;
2229
queryClientKey?: string;
2330
additionalClients?: AdditionalClient[];
31+
contextSharing?: boolean;
2432
}
2533

2634
export type VueQueryPluginOptions = ConfigOptions | ClientOptions;
@@ -33,9 +41,24 @@ export const VueQueryPlugin = {
3341
if ("queryClient" in options && options.queryClient) {
3442
client = options.queryClient;
3543
} else {
36-
const clientConfig =
37-
"queryClientConfig" in options ? options.queryClientConfig : undefined;
38-
client = new QueryClient(clientConfig);
44+
if (options.contextSharing && typeof window !== "undefined") {
45+
if (!window.__VUE_QUERY_CONTEXT__) {
46+
const clientConfig =
47+
"queryClientConfig" in options
48+
? options.queryClientConfig
49+
: undefined;
50+
client = new QueryClient(clientConfig);
51+
window.__VUE_QUERY_CONTEXT__ = client;
52+
} else {
53+
client = window.__VUE_QUERY_CONTEXT__;
54+
}
55+
} else {
56+
const clientConfig =
57+
"queryClientConfig" in options
58+
? options.queryClientConfig
59+
: undefined;
60+
client = new QueryClient(clientConfig);
61+
}
3962
}
4063

4164
client.mount();

0 commit comments

Comments
 (0)