Skip to content

Using Fragments

Fragments let you split complex queries into reusable pieces and colocate data requirements with components.

What Are Fragments?

Fragments define data requirements for a specific component:

typescript
const UserCard_user = graphql(`
  fragment UserCard_user on User {
    id
    name
    avatar
  }
`);

This allows each component to declare exactly what data it needs, instead of parent components knowing all child requirements.

Define a Fragment

Define a fragment with your component:

tsx
// src/components/UserCard.tsx
import { graphql } from 'mearie';
import { useFragment } from '@mearie/react';
import type { UserCard_user$key } from 'mearie/types';

export const UserCard = ({ user }: { user: UserCard_user$key }) => {
  const data = useFragment(
    graphql(`
      fragment UserCard_user on User {
        id
        name
        avatar
        email
      }
    `),
    user,
  );

  return (
    <div className="card">
      <img src={data.avatar} alt={data.name} />
      <h3>{data.name}</h3>
      <p>{data.email}</p>
    </div>
  );
};
vue
<!-- src/components/UserCard.vue -->
<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>
svelte
<!-- src/components/UserCard.svelte -->
<script lang="ts">
import { graphql } from 'mearie';
import { createFragment } from '@mearie/svelte';
import type { UserCard_user$key } from 'mearie/types';

interface Props {
  user: UserCard_user$key;
}

let { user }: Props = $props();

const data = createFragment(
  graphql(`
    fragment UserCard_user on User {
      id
      name
      avatar
      email
    }
  `),
  () => user,
);
</script>

<div class="card">
  <img src={data.avatar} alt={data.name} />
  <h3>{data.name}</h3>
  <p>{data.email}</p>
</div>
tsx
// src/components/UserCard.tsx
import { type Component } from 'solid-js';
import { graphql } from 'mearie';
import { createFragment } from '@mearie/solid';
import type { UserCard_user$key } from 'mearie/types';

interface UserCardProps {
  user: UserCard_user$key;
}

export const UserCard: Component<UserCardProps> = (props) => {
  const data = createFragment(
    graphql(`
      fragment UserCard_user on User {
        id
        name
        avatar
        email
      }
    `),
    () => props.user,
  );

  return (
    <div class="card">
      <img src={data().avatar} alt={data().name} />
      <h3>{data().name}</h3>
      <p>{data().email}</p>
    </div>
  );
};

Each component declares its own data requirements with useFragment (or createFragment in Svelte/Solid).

Use the Fragment

Use the fragment in your query:

tsx
// src/pages/UserProfile.tsx
import { graphql } from 'mearie';
import { useQuery } from '@mearie/react';
import { UserCard } from '../components/UserCard';

export const UserProfile = ({ userId }: { userId: string }) => {
  const { data } = useQuery(
    graphql(`
      query GetUserQuery($id: ID!) {
        user(id: $id) {
          ...UserCard_user
        }
      }
    `),
    { id: userId },
  );

  return <UserCard user={data.user} />;
};
vue
<!-- src/pages/UserProfile.vue -->
<script setup lang="ts">
import { graphql } from 'mearie';
import { useQuery } from '@mearie/vue';
import UserCard from '../components/UserCard.vue';

const props = defineProps<{ userId: string }>();

const { data } = useQuery(
  graphql(`
    query GetUserQuery($id: ID!) {
      user(id: $id) {
        ...UserCard_user
      }
    }
  `),
  () => ({ id: props.userId }),
);
</script>

<template>
  <UserCard :user="data.user" />
</template>
svelte
<!-- src/pages/UserProfile.svelte -->
<script lang="ts">
import { graphql } from 'mearie';
import { createQuery } from '@mearie/svelte';
import UserCard from '../components/UserCard.svelte';

interface Props {
  userId: string;
}

let { userId }: Props = $props();

const query = createQuery(
  graphql(`
    query GetUserQuery($id: ID!) {
      user(id: $id) {
        ...UserCard_user
      }
    }
  `),
  () => ({ id: userId }),
);
</script>

<UserCard user={query.data.user} />
tsx
// src/pages/UserProfile.tsx
import { type Component } from 'solid-js';
import { graphql } from 'mearie';
import { createQuery } from '@mearie/solid';
import { UserCard } from '../components/UserCard';

interface UserProfileProps {
  userId: string;
}

export const UserProfile: Component<UserProfileProps> = (props) => {
  const query = createQuery(
    graphql(`
      query GetUserQuery($id: ID!) {
        user(id: $id) {
          ...UserCard_user
        }
      }
    `),
    () => ({ id: props.userId }),
  );

  return <UserCard user={query.data.user} />;
};

TypeScript ensures the fragment is spread in the query and the correct data is passed to the component.

Next Steps