Skip to content

Commit

Permalink
feat: support effect scope outside of component, fix #1505
Browse files Browse the repository at this point in the history
  • Loading branch information
Akryum committed Sep 12, 2023
1 parent 574bd8f commit f5e371f
Show file tree
Hide file tree
Showing 10 changed files with 205 additions and 27 deletions.
1 change: 1 addition & 0 deletions packages/test-e2e-composable-vue3/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
"@vue/apollo-util": "workspace:*",
"graphql": "^16.7.1",
"graphql-tag": "^2.12.6",
"pinia": "^2.1.6",
"test-server": "workspace:*",
"vue": "^3.3.4",
"vue-router": "^4.2.4"
Expand Down
31 changes: 15 additions & 16 deletions packages/test-e2e-composable-vue3/src/components/App.vue
Original file line number Diff line number Diff line change
@@ -1,22 +1,21 @@
<script lang="ts" setup>
import { computed } from 'vue'
import ChannelList from './ChannelList.vue'
import GlobalLoading from './GlobalLoading.vue'
import { useRoute } from 'vue-router'
const route = useRoute()
const displayChannels = computed(() => !route.matched.some(r => r.meta?.layout === 'blank'))
</script>

<template>
<GlobalLoading />
<div class="flex h-screen items-stretch bg-gray-100">
<ChannelList class="w-1/4 border-r border-gray-200" />
<ChannelList
v-if="displayChannels"
class="w-1/4 border-r border-gray-200"
/>
<router-view class="flex-1 overflow-auto" />
</div>
</template>

<script lang="ts">
import { defineComponent } from 'vue'
import ChannelList from './ChannelList.vue'
import GlobalLoading from './GlobalLoading.vue'
export default defineComponent({
name: 'App',
components: {
ChannelList,
GlobalLoading,
},
})
</script>
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<script lang="ts" setup>
import { useChannels } from '@/stores/channel'
const channelStore = useChannels()
</script>

<template>
<div
v-if="channelStore.loading"
class="p-12 text-gray-500"
>
Loading channels...
</div>

<div
v-else
class="flex flex-col bg-white"
>
<router-link
v-for="channel of channelStore.channels"
:key="channel.id"
v-slot="{ href, navigate, isActive }"
:to="{
name: 'channel',
params: {
id: channel.id,
},
}"
custom
>
<a
:href="href"
class="channel-link px-4 py-2 hover:bg-green-100 text-green-700"
:class="{
'bg-green-200 hover:bg-green-300 text-green-900': isActive,
}"
@click="navigate"
>
# {{ channel.label }}
</a>
</router-link>
</div>
</template>
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<script lang="ts" setup>
import { useChannels } from '@/stores/channel'
import { onBeforeUnmount, ref, watch } from 'vue'
const channels = ref<any[]>([])

Check warning on line 5 in packages/test-e2e-composable-vue3/src/components/ChannelListPinia2.vue

View workflow job for this annotation

GitHub Actions / Build and test

Unexpected any. Specify a different type
let unwatch: (() => void) | undefined
setTimeout(() => {
const channelStore = useChannels()
unwatch = watch(() => channelStore.channels, (newChannels) => {
channels.value = newChannels
}, {
immediate: true,
})
}, 0)
onBeforeUnmount(() => {
unwatch?.()
})
</script>

<template>
<div
v-if="channels"
class="flex flex-col bg-white"
>
<router-link
v-for="channel of channels"
:key="channel.id"
v-slot="{ href, navigate, isActive }"
:to="{
name: 'channel',
params: {
id: channel.id,
},
}"
custom
>
<a
:href="href"
class="channel-link px-4 py-2 hover:bg-green-100 text-green-700"
:class="{
'bg-green-200 hover:bg-green-300 text-green-900': isActive,
}"
@click="navigate"
>
# {{ channel.label }}
</a>
</router-link>
</div>
</template>
12 changes: 5 additions & 7 deletions packages/test-e2e-composable-vue3/src/main.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
import { createApp, h, provide } from 'vue'
import { createApp } from 'vue'
import { DefaultApolloClient } from '@vue/apollo-composable'
import { createPinia } from 'pinia'
import { apolloClient } from './apollo'
import App from './components/App.vue'
import { router } from './router'
import '@/assets/styles/tailwind.css'

const app = createApp({
setup () {
provide(DefaultApolloClient, apolloClient)
},
render: () => h(App),
})
const app = createApp(App)
app.use(createPinia())
app.use(router)
app.provide(DefaultApolloClient, apolloClient)
app.mount('#app')
14 changes: 14 additions & 0 deletions packages/test-e2e-composable-vue3/src/router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,5 +50,19 @@ export const router = createRouter({
path: '/null-query',
component: () => import('./components/NullQuery.vue'),
},
{
path: '/pinia',
component: () => import('./components/ChannelListPinia.vue'),
meta: {
layout: 'blank',
},
},
{
path: '/pinia2',
component: () => import('./components/ChannelListPinia2.vue'),
meta: {
layout: 'blank',
},
},
],
})
33 changes: 33 additions & 0 deletions packages/test-e2e-composable-vue3/src/stores/channel.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import gql from 'graphql-tag'
import { useQuery } from '@vue/apollo-composable'
import { defineStore } from 'pinia'
import { computed, watch } from 'vue'

interface Channel {
id: string
label: string
}

export const useChannels = defineStore('channel', () => {
const query = useQuery<{ channels: Channel[] }>(gql`
query channels {
channels {
id
label
}
}
`)

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

watch(query.loading, value => {
console.log('loading', value)
}, {
immediate: true,
})

return {
loading: query.loading,
channels,
}
})
19 changes: 19 additions & 0 deletions packages/test-e2e-composable-vue3/tests/e2e/specs/pinia.cy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
describe('Pinia', () => {
beforeEach(() => {
cy.task('db:reset')
})

it('with current instance', () => {
cy.visit('/pinia')
cy.get('.channel-link').should('have.lengthOf', 2)
cy.contains('.channel-link', '# General')
cy.contains('.channel-link', '# Random')
})

it('with effect scope only', () => {
cy.visit('/pinia2')
cy.get('.channel-link').should('have.lengthOf', 2)
cy.contains('.channel-link', '# General')
cy.contains('.channel-link', '# Random')
})
})
6 changes: 3 additions & 3 deletions packages/vue-apollo-composable/src/useApolloClient.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { getCurrentInstance, inject } from 'vue-demi'
import { getCurrentInstance, getCurrentScope, inject } from 'vue-demi'
import { ApolloClient } from '@apollo/client/core/index.js'

export const DefaultApolloClient = Symbol('default-apollo-client')
Expand Down Expand Up @@ -35,7 +35,7 @@ export function useApolloClient<TCacheShape = any> (clientId?: ClientId): UseApo
// Save current client in current closure scope
const savedCurrentClients = currentApolloClients

if (!getCurrentInstance()) {
if (!getCurrentInstance() && !getCurrentScope()) {
resolveImpl = (id?: ClientId) => {
if (id) {
return resolveClientWithId(savedCurrentClients, id)
Expand Down Expand Up @@ -68,7 +68,7 @@ export function useApolloClient<TCacheShape = any> (clientId?: ClientId): UseApo
throw new Error(
`Apollo client with id ${
id ?? 'default'
} not found. Use provideApolloClient() if you are outside of a component setup.`,
} not found. Use an app.runWithContext() or provideApolloClient() if you are outside of a component setup.`,
)
}
return client
Expand Down
22 changes: 21 additions & 1 deletion pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit f5e371f

Please sign in to comment.