Skip to content

Commit

Permalink
refactor: initial version
Browse files Browse the repository at this point in the history
  • Loading branch information
posva committed Sep 26, 2024
1 parent d146bfd commit 2b5802a
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 16 deletions.
2 changes: 2 additions & 0 deletions src/query-store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -481,6 +481,8 @@ export const useQueryCache = defineStore(QUERY_STORE_ID, ({ action }) => {
entry.asyncStatus.value = 'idle'
if (pendingCall === entry.pending) {
entry.pending = null
// reset the placeholder data to free up memory
entry.placeholderData = null
entry.when = Date.now()
}
}),
Expand Down
30 changes: 26 additions & 4 deletions src/use-query.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -372,22 +372,44 @@ describe('useQuery', () => {
describe('placeholderData', () => {
it('affects useQuery data, state, status', async () => {
const { wrapper } = mountSimple({
query: async () => {
await new Promise((r) => setTimeout(r, 100))
return 42
},
query: async () => 42,
placeholderData: 24,
})

expect(wrapper.vm.isPlaceholderData).toBe(true)
expect(wrapper.vm.state).toEqual({
data: 24,
error: null,
status: 'success',
})
expect(wrapper.vm.data).toBe(24)
expect(wrapper.vm.isLoading).toBe(true)
expect(wrapper.vm.isPending).toBe(false)
expect(wrapper.vm.status).toBe('success')
expect(wrapper.vm.error).toBeNull()
expect(wrapper.vm.asyncStatus).toBe('loading')

await flushPromises()
expect(wrapper.vm.isPlaceholderData).toBe(false)
expect(wrapper.vm.data).toBe(42)
})

it('works with a function', async () => {
const { wrapper } = mountSimple({
query: async () => 42,
placeholderData: () => 24,
})

expect(wrapper.vm.data).toBe(24)
await flushPromises()
expect(wrapper.vm.data).toBe(42)
})

it.todo('ignores the placeholderData if there is already data in the cache')
it.todo('ignores the placeholderData if there is already an error in the cache')
it.todo('ignores the placeholderData if it returns a nullish value')

it.todo('calls the placeholderData function with the previous data if the entry key changes')
})

describe('refresh data', () => {
Expand Down
32 changes: 20 additions & 12 deletions src/use-query.ts
Original file line number Diff line number Diff line change
Expand Up @@ -157,20 +157,29 @@ export function useQuery<TResult, TError = ErrorDefault>(
entry.value.placeholderData != null
&& entry.value.state.value.status === 'pending',
)
const state = computed<DataState<TResult, TError>>(() =>
isPlaceholderData.value
? {
status: 'success',
data: entry.value.placeholderData!,
error: null,
}
: entry.value.state.value,
)

// TODO: adapt to use the placeholderData in data and state
// and to change the status to success

const queryReturn = {
state: computed(() => entry.value.state.value),
state,

status: computed(() => entry.value.state.value.status),
data: computed(() => entry.value.state.value.data),
status: computed(() => state.value.status),
data: computed(() => state.value.data),
error: computed(() => entry.value.state.value.error),
asyncStatus: computed(() => entry.value.asyncStatus.value),

isPlaceholderData,
isPending: computed(() => entry.value.state.value.status === 'pending'),
isPending: computed(() => state.value.status === 'pending'),
isLoading: computed(() => entry.value.asyncStatus.value === 'loading'),

refresh,
Expand Down Expand Up @@ -213,6 +222,13 @@ export function useQuery<TResult, TError = ErrorDefault>(
watch(
entry,
(entry, previousEntry) => {
// the placeholderData is only used if the entry is initially loading
if (options.placeholderData && entry.state.value.status === 'pending') {
entry.placeholderData = toValueWithArgs(
options.placeholderData,
previousEntry?.state.value.data,
)
}
if (!isActive) return
if (previousEntry) {
queryEntry_removeDep(previousEntry, hasCurrentInstance, cacheEntries)
Expand All @@ -223,14 +239,6 @@ export function useQuery<TResult, TError = ErrorDefault>(
queryEntry_addDep(entry, currentEffect)

if (toValue(options.enabled)) refresh()

// the placeholderData is only used if the entry is initially loading
if (options.placeholderData && entry.state.value.status === 'pending') {
entry.placeholderData = toValueWithArgs(
options.placeholderData,
previousEntry?.state.value.data,
)
}
},
{ immediate: true },
)
Expand Down

0 comments on commit 2b5802a

Please sign in to comment.