Skip to content

Commit 0665635

Browse files
committed
fix(data-loaders): allow nested loaders to run on invalidation
Fix #583
1 parent 2023940 commit 0665635

File tree

2 files changed

+72
-13
lines changed

2 files changed

+72
-13
lines changed

src/data-loaders/defineColadaLoader.spec.ts

+52
Original file line numberDiff line numberDiff line change
@@ -324,5 +324,57 @@ describe(
324324

325325
expect(getCurrentContext()).toEqual([])
326326
})
327+
328+
it('can refetch nested loaders on invalidation', async () => {
329+
const nestedQuery = vi.fn(async () => [{ id: 0 }, { id: 1 }])
330+
const useListData = defineColadaLoader({
331+
query: nestedQuery,
332+
key: () => ['list'],
333+
})
334+
335+
const useDetailData = defineColadaLoader({
336+
key: (to) => ['list', to.params.id as string],
337+
async query(to) {
338+
const list = await useListData()
339+
const item = list.find(
340+
(item) => String(item.id) === (to.params.id as string)
341+
)
342+
if (!item) {
343+
throw new Error('Not Found')
344+
}
345+
return { ...item, when: Date.now() }
346+
},
347+
})
348+
349+
const component = defineComponent({
350+
setup() {
351+
return { ...useDetailData() }
352+
},
353+
template: `<p/>`,
354+
})
355+
356+
const router = getRouter()
357+
router.addRoute({
358+
name: 'item-id',
359+
path: '/items/:id',
360+
meta: { loaders: [useDetailData] },
361+
component,
362+
})
363+
364+
const pinia = createPinia()
365+
366+
mount(RouterViewMock, {
367+
global: {
368+
plugins: [[DataLoaderPlugin, { router }], pinia, PiniaColada],
369+
},
370+
})
371+
372+
await router.push('/items/0')
373+
const queryCache = useQueryCache(pinia)
374+
375+
await expect(
376+
queryCache.invalidateQueries({ key: ['list'] })
377+
).resolves.toBeDefined()
378+
})
327379
}
328380
)

src/data-loaders/defineColadaLoader.ts

+20-13
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,8 @@ export function defineColadaLoader<Data>(
168168
// set the current context before loading so nested loaders can use it
169169
setCurrentContext([entry, router, to])
170170

171+
const app = router[APP_KEY]
172+
171173
if (!entry.ext) {
172174
// console.log(`🚀 creating query for "${key}"`)
173175
entry.ext = useQuery({
@@ -185,9 +187,13 @@ export function defineColadaLoader<Data>(
185187
}
186188
)
187189

188-
return loader(trackedRoute, {
189-
signal: route.meta[ABORT_CONTROLLER_KEY]?.signal,
190-
})
190+
// needed for automatic refetching and nested loaders
191+
// https://github.com/posva/unplugin-vue-router/issues/583
192+
return app.runWithContext(() =>
193+
loader(trackedRoute, {
194+
signal: route.meta[ABORT_CONTROLLER_KEY]?.signal,
195+
})
196+
)
191197
},
192198
key: () => toValueWithParameters(options.key, entry.route.value),
193199
// TODO: cleanup if gc
@@ -380,6 +386,7 @@ export function defineColadaLoader<Data>(
380386
// fallback to the global router and routes for useDataLoaders used within components
381387
const router = _router || useRouter()
382388
const route = _route || (useRoute() as RouteLocationNormalizedLoaded)
389+
const app = router[APP_KEY]
383390

384391
const entries = router[
385392
LOADER_ENTRIES_KEY
@@ -399,7 +406,7 @@ export function defineColadaLoader<Data>(
399406
// console.log(
400407
// `🔁 loading from useData for "${options.key}": "${route.fullPath}"`
401408
// )
402-
router[APP_KEY].runWithContext(() =>
409+
app.runWithContext(() =>
403410
// in this case we always need to run the functions for nested loaders consistency
404411
load(route, router, undefined, parentEntry, true)
405412
)
@@ -447,22 +454,22 @@ export function defineColadaLoader<Data>(
447454
error,
448455
isLoading,
449456
reload: (to: RouteLocationNormalizedLoaded = router.currentRoute.value) =>
450-
router[APP_KEY].runWithContext(() =>
451-
load(to, router, undefined, undefined, true)
452-
).then(() => entry!.commit(to)),
457+
app
458+
.runWithContext(() => load(to, router, undefined, undefined, true))
459+
.then(() => entry!.commit(to)),
453460
// pinia colada
454461
refetch: (
455462
to: RouteLocationNormalizedLoaded = router.currentRoute.value
456463
) =>
457-
router[APP_KEY].runWithContext(() =>
458-
load(to, router, undefined, undefined, true)
459-
).then(() => (entry!.commit(to), entry!.ext!.state.value)),
464+
app
465+
.runWithContext(() => load(to, router, undefined, undefined, true))
466+
.then(() => (entry!.commit(to), entry!.ext!.state.value)),
460467
refresh: (
461468
to: RouteLocationNormalizedLoaded = router.currentRoute.value
462469
) =>
463-
router[APP_KEY].runWithContext(() => load(to, router)).then(
464-
() => (entry!.commit(to), entry.ext!.state.value)
465-
),
470+
app
471+
.runWithContext(() => load(to, router))
472+
.then(() => (entry!.commit(to), entry.ext!.state.value)),
466473
status: ext!.status,
467474
asyncStatus: ext!.asyncStatus,
468475
state: ext!.state,

0 commit comments

Comments
 (0)