Skip to content

Commit

Permalink
feat: add updateQuery to useQuery (#1552)
Browse files Browse the repository at this point in the history
  • Loading branch information
syllomex committed Aug 14, 2024
1 parent f236070 commit d1098be
Show file tree
Hide file tree
Showing 4 changed files with 185 additions and 0 deletions.
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

0 comments on commit d1098be

Please sign in to comment.