Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add updateQuery to useQuery #1552

Merged
merged 2 commits into from
Aug 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
141 changes: 141 additions & 0 deletions packages/test-e2e-composable-vue3/src/components/UpdateQuery.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
<script lang="ts" setup>
import { useMutation, useQuery } from '@vue/apollo-composable'
import gql from 'graphql-tag'
import { computed, ref } from 'vue'
import MessageItem from './MessageItem.vue'

interface Channel {
id: string
label: string
}

const channelsQuery = useQuery<{ channels: Channel[] }>(gql`
query channels {
channels {
id
label
}
}
`)

const channels = computed(() => channelsQuery.result.value?.channels ?? [])

const selectedChannelId = ref<string | null>(null)

const selectedChannelQuery = useQuery(gql`
query channel ($id: ID!) {
channel (id: $id) {
id
label
messages {
id
text
}
}
}
`, () => ({
id: selectedChannelId.value,
}), () => ({
enabled: !!selectedChannelId.value,
}))

const addMessageMutation = useMutation(gql`
mutation sendMessage ($input: AddMessageInput!) {
message: addMessage (input: $input) {
id
text
}
}
`)

const selectedChannel = computed(() => selectedChannelQuery.result.value?.channel)

const newMessageText = ref('')

async function sendMessage () {
if (!newMessageText.value.length) return

const result = await addMessageMutation.mutate({
input: {
channelId: selectedChannelId.value,
text: newMessageText.value,
},
})

newMessageText.value = ''

selectedChannelQuery.updateQuery(previousResult => ({
...previousResult,
channel: {
...previousResult.channel,
messages: [
...previousResult.channel.messages,
result?.data.message,
],
},
}))
}
</script>

<template>
<div class="h-full flex flex-col">
<div class="flex h-full">
<div class="flex flex-col">
<button
v-for="channel of channels"
:key="channel.id"
class="channel-btn p-4"
:class="{
'bg-green-200': selectedChannelId === channel.id,
}"
@click="selectedChannelId = channel.id"
>
{{ channel.label }}
</button>
</div>

<div
v-if="selectedChannel"
class="the-channel flex flex-col w-full h-full overflow-auto"
>
<div class="flex-none p-6 border-b border-gray-200 bg-white">
# {{ selectedChannel.label }}
</div>

<div class="flex-1 overflow-y-auto">
<MessageItem
v-for="message of selectedChannel.messages"
:key="message.id"
:message="message"
class="m-2"
/>
</div>

<div class="flex gap-x-2 p-4">
<div class="border border-gray-200 rounded-lg bg-white flex-1">
<input
v-model="newMessageText"
type="text"
class="message-input w-full h-full bg-transparent px-3"
placeholder="Type a message..."
>
</div>

<button
class="send-message-btn bg-green-200 py-3 px-4 rounded-lg"
@click="sendMessage"
>
Send
</button>
</div>
</div>

<div
v-else
class="no-data"
>
No data
</div>
</div>
</div>
</template>
4 changes: 4 additions & 0 deletions packages/test-e2e-composable-vue3/src/router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,5 +93,9 @@ export const router = createRouter({
layout: 'blank',
},
},
{
path: '/update-query',
component: () => import('./components/UpdateQuery.vue'),
},
],
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
describe('updateQuery', () => {
beforeEach(() => {
cy.task('db:reset')
cy.visit('/update-query')
})

it('should add new message to cache using updateQuery', () => {
cy.get('.channel-btn').eq(0).click()
cy.get('.message-input').type('hello 1')
cy.get('.message').should('have.lengthOf', 0)
cy.get('.send-message-btn').click()
cy.get('.message').should('have.lengthOf', 1)
cy.get('.message-input').type('hello 2')
cy.get('.send-message-btn').click()
cy.get('.message').should('have.lengthOf', 2)
cy.contains('.message', 'hello 1')
cy.contains('.message', 'hello 2')

cy.get('.channel-btn').eq(1).click()
cy.get('.message-input').type('hello 3')
cy.get('.message').should('have.lengthOf', 0)
cy.get('.send-message-btn').click()
cy.get('.message').should('have.lengthOf', 1)
cy.get('.message-input').type('hello 4')
cy.get('.send-message-btn').click()
cy.get('.message').should('have.lengthOf', 2)
cy.contains('.message', 'hello 3')
cy.contains('.message', 'hello 4')
})
})
10 changes: 10 additions & 0 deletions packages/vue-apollo-composable/src/useQuery.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ export interface UseQueryReturn<TResult, TVariables extends OperationVariables>
query: Ref<ObservableQuery<TResult, TVariables> | null | undefined>
refetch: (variables?: TVariables) => Promise<ApolloQueryResult<TResult>> | undefined
fetchMore: (options: FetchMoreQueryOptions<TVariables, TResult> & FetchMoreOptions<TResult, TVariables>) => Promise<ApolloQueryResult<TResult>> | undefined
updateQuery: (mapFn: (previousQueryResult: TResult, options: Pick<WatchQueryOptions<TVariables, TResult>, 'variables'>) => TResult) => void
subscribeToMore: <TSubscriptionVariables = OperationVariables, TSubscriptionData = TResult>(options: SubscribeToMoreOptions<TResult, TSubscriptionVariables, TSubscriptionData> | Ref<SubscribeToMoreOptions<TResult, TSubscriptionVariables, TSubscriptionData>> | ReactiveFunction<SubscribeToMoreOptions<TResult, TSubscriptionVariables, TSubscriptionData>>) => void
onResult: (fn: (param: ApolloQueryResult<TResult>, context: OnResultContext) => void) => {
off: () => void
Expand Down Expand Up @@ -534,6 +535,14 @@ export function useQueryImpl<
}
}

// Update Query

function updateQuery (mapFn: (previousQueryResult: TResult, options: Pick<WatchQueryOptions<TVariables, TResult>, 'variables'>) => TResult) {
if (query.value) {
query.value.updateQuery(mapFn)
}
}

// Fetch more

function fetchMore (options: FetchMoreQueryOptions<TVariables, TResult> & FetchMoreOptions<TResult, TVariables>) {
Expand Down Expand Up @@ -637,6 +646,7 @@ export function useQueryImpl<
refetch,
fetchMore,
subscribeToMore,
updateQuery,
onResult: resultEvent.on,
onError: errorEvent.on,
}
Expand Down
Loading