Vue Integration
Mearie provides Vue composables that integrate seamlessly with Vue's reactive system for automatic query refetching and full type safety.
Installation
Install the core package and the Vue integration:
npm install mearie @mearie/vue
yarn add mearie @mearie/vue
pnpm add mearie @mearie/vue
bun add mearie @mearie/vue
deno add npm:mearie npm:@mearie/vue
Setup
1. Add Build Plugin
Add Mearie's build plugin to enable automatic type generation from your GraphQL documents:
// vite.config.ts
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
import mearie from 'mearie/vite';
export default defineConfig({
plugins: [vue(), mearie()],
});
TIP
By default, Mearie looks for ./schema.graphql
relative to your vite.config.ts
. For custom schema locations or advanced configuration, see Codegen Config.
2. Create Client
Create a GraphQL client with your API endpoint. Links are middleware-style handlers that process requests and responses. At least one terminating link is required (in this case, httpLink
). See Links for more details.
// src/lib/graphql-client.ts
import { createClient, httpLink, cacheLink, dedupLink } from 'mearie';
export const client = createClient({
links: [
dedupLink(),
cacheLink(),
httpLink({
url: 'https://api.example.com/graphql',
}),
],
});
3. Set Up Provider
Wrap your app with the client provider to make the GraphQL client available throughout your component tree:
// src/main.ts
import { ClientPlugin } from '@mearie/vue';
import { client } from './lib/graphql-client';
app.use(ClientPlugin, { client });
Composables
useQuery
Fetch data with automatic caching:
<script setup lang="ts">
import { graphql } from 'mearie';
import { useQuery } from '@mearie/vue';
const props = defineProps<{ userId: string }>();
const { data, loading, error, refetch } = useQuery(
graphql(`
query GetUserQuery($id: ID!) {
user(id: $id) {
id
name
email
avatar
bio
age
}
}
`),
() => ({ id: props.userId }),
);
</script>
<template>
<div v-if="loading">Loading...</div>
<div v-else-if="error">Error: {{ error.message }}</div>
<div v-else>
<img :src="data.user.avatar" :alt="data.user.name" />
<h1>{{ data.user.name }}</h1>
<p v-if="data.user.bio">{{ data.user.bio }}</p>
<p>Email: {{ data.user.email }}</p>
<p>Age: {{ data.user.age }}</p>
<button @click="refetch()">Refresh</button>
</div>
</template>
useMutation
Modify data with automatic cache updates:
<script setup lang="ts">
import { ref } from 'vue';
import { graphql } from 'mearie';
import { useMutation } from '@mearie/vue';
const props = defineProps<{ userId: string }>();
const name = ref('');
const { mutate, loading } = useMutation(
graphql(`
mutation UpdateUserMutation($id: ID!, $name: String!) {
updateUser(id: $id, input: { name: $name }) {
id
name
}
}
`),
);
const handleSubmit = async () => {
await mutate({ id: props.userId, name: name.value });
};
</script>
<template>
<form @submit.prevent="handleSubmit">
<input v-model="name" required />
<button :disabled="loading">{{ loading ? 'Saving...' : 'Save' }}</button>
</form>
</template>
useFragment
Co-locate data requirements with components:
<script setup lang="ts">
import { graphql } from 'mearie';
import { useFragment } from '@mearie/vue';
import type { UserCard_user$key } from 'mearie/types';
const props = defineProps<{ user: UserCard_user$key }>();
const data = useFragment(
graphql(`
fragment UserCard_user on User {
id
name
avatar
email
}
`),
() => props.user,
);
</script>
<template>
<div class="card">
<img :src="data.avatar" :alt="data.name" />
<h3>{{ data.name }}</h3>
<p>{{ data.email }}</p>
</div>
</template>
useSubscription
Real-time updates via subscriptions:
<script setup lang="ts">
import { graphql } from 'mearie';
import { useSubscription } from '@mearie/vue';
const props = defineProps<{ chatId: string }>();
const { data, loading } = useSubscription(
graphql(`
subscription MessageAddedSubscription($chatId: ID!) {
messageAdded(chatId: $chatId) {
id
body
author {
name
}
}
}
`),
() => ({ chatId: props.chatId }),
);
</script>
<template>
<div>
<div>{{ loading ? 'Connecting...' : 'Connected' }}</div>
<div v-if="data?.messageAdded">
<strong>{{ data.messageAdded.author.name }}:</strong>
{{ data.messageAdded.body }}
</div>
</div>
</template>
Reactive Variables
Variables automatically track Vue reactivity:
<script setup lang="ts">
import { ref, computed } from 'vue';
import { graphql } from 'mearie';
import { useQuery } from '@mearie/vue';
const userId = ref('123');
// Automatically refetches when userId changes
const { data } = useQuery(
graphql(`
query GetUserQuery($id: ID!) {
user(id: $id) {
id
name
email
}
}
`),
() => ({ id: userId.value }),
);
// Or with computed
const variables = computed(() => ({ id: userId.value }));
const { data: data2 } = useQuery(
graphql(`
query GetUserQuery($id: ID!) {
user(id: $id) {
id
name
email
}
}
`),
variables,
);
</script>
<template>
<div v-if="data">
<h1>{{ data.user.name }}</h1>
</div>
</template>
Next Steps
- Queries - Learn more about queries
- Mutations - Learn more about mutations
- Fragments - Learn more about fragments
- Subscriptions - Learn more about subscriptions