---
title: Loading States
description: An overview of the tools that houdini provides to help construct loading states for your application.
---

<script>
    import LoadingPokedex from '~/components/pokedex/LoadingState.svelte'
    import { DeepDive } from '~/components'
</script>

# Loading States

At some point, your users are going to be waiting for data to load from the server. This could be because they
don't live in a place with state-of-the-art internet service or maybe they just stepped into a tunnel. Regardless,
you are going to want to show them _something_ while your request loads. These loading states are sometimes referred
to as "Skeleton UIs" and usually display placeholder elements while the actual content is being loaded.

This guide will go over all of the tools that Houdini provides to help you build these interfaces.

## A Concrete Example

Before we get too far, let's look at a concrete example so we can have a goal in mind. For this guide,
we're going to be building a loading screen for the Pokédex that we constructed in the [Getting Started](/intro) guide:

<p>
    <LoadingPokedex />
</p>

For the sake of this guide, you can imagine that the Pokedex is built using the following route:

```graphql:title=src/routes/[[id]]/+page.qgl
query SpeciesInfo($id: Int = 1) {
    species(id: $id) {
        name
        description
        evolutionChain {
            name
            ...Sprite_species
        }

        ...Sprite_species
        ...MoveList_species
        ...NavButtons_species
    }
}
```

```svelte:title=src/routes/[[id]]/+page.svelte&typescriptToggle=true
<script lang="ts">
    import type { PageData } from './$houdini'
    // prettier-ignore
    import {
        Container,
        Panel,
        Sprite,
        Display,
        MoveList,
        NavButtons_species,
        Number,
    } from '~/components'

    export let data: PageData

    let { SpeciesInfo } = data
    $: ({ SpeciesInfo } = data)

    $: species = $SpeciesInfo.data?.species
</script>

<Container>
    <Panel slot="left">
        <Display>
            {species.name}
        </Display>
        <Sprite {species} />
        <Display>
            {species.description}
        </Display>
    </Panel>
    <Panel slot="right">
        <div class="evolution-chain">
            {#each species.evolutionChain as evolvedForm, i }
                <div class="evolution-form">
                    <Number value={i + 1} />
                    <Sprite style="height: 96px;" species={evolvedForm} />
                    <Display>
                        {evolvedForm.name}
                    </Display>
                </div>
            {/each}
        </div>
        <MoveList {species} />
        <NavButtons {species} />
    </Panel>
</Container>
```

Just in case it's not clear: the `evolutionChain` list corresponds to the 3 columns
in the top right of the loading screen above. If it helps, you can look at a deployed
version of the application [here](http://houdini-intro.pages.dev).

## The Simplest Solution

If you followed along in the [Getting Started Guide](/intro) then you know that if we click on the
`next` button in that example then our application will crash. This is
because `data` is `null` when the query is loading a new value which causes
`$SpeciesInfo.data.species` to explode. The easiest way to protect against
this is to check the `fetching` value of the store and render your loading state.

Sorry in advanced about the length of the following example but it highlights one of the primary points
I'm trying to illustrate: this approach duplicates a _lot_ of logic and structure.

```svelte:title=src/routes/[[id]]/+page.svelte&typescriptToggle=true
<script lang="ts">
    // ...

    $: species = $SpeciesInfo.data?.species
</script>

{#if $SpeciesInfo.fetching}
    <Container>
        <Panel slot="left">
            <Display height={30} loading />
            <Sprite style="flex-grow:1" loading />
            <Display height={120} loading/>
        </Panel>
        <Panel slot="right">
            <div class="evolution-chain">
                {#each Array.from({length: 3}) as _, i }
                    <div class="evolution-form">
                        <Number value={i + 1} />
                        <Sprite height={96} loading />
                        <Display height={30} loading />
                    </div>
                {/each}
            </div>
            <div class="row">
                <Display height={400} loading />
                <UpDownButtons disabled />
            </div>
            <div class="row">
                <Button disabled>Previous</Button>
                <Button disabled>Next</Button>
            </div>
        </Panel>
    </Container>
{:else}
    <Container>
        <Panel slot="left">
            <Display>
                {species.name}
            </Display>
            <Sprite {species} />
            <Display>
                {species.description}
            </Display>
        </Panel>
        <Panel slot="right">
            <div class="evolution-chain">
                {#each species.evolutionChain as evolvedForm, i }
                    <div class="evolution-form">
                        <Number value={number + 1} />
                        <Sprite style="height: 96px;" species={node} />
                        <Display>
                            {node.name}
                        </Display>
                    </div>
                {/each}
            </div>
            <MoveList {species} />
            <NavButtons {species} />
        </Panel>
    </Container>
{/if}
```

There are 2 major problems with this:

1. We basically have to build our layout twice. Even if we relied heavily on the `?` operator or sprinkled a bunch of `#if $SpeciesInfo.fetching` everywhere, we still _must_ duplicate the logic for the evolution chain since when
   `data` is null, there is no natural list to iterate over to render the boxes.
1. We had to break the abstraction created by the `MoveList` and `NavButtons` components since we needed to
   duplicate their structure here (something this component is supposed to know nothing about).

Bottom Line? No matter how we approach it, if our goal is to build a loading state that reflects our final UI, relying
on the `fetching` value is pretty annoying.
But don't worry - Houdini solves both of these problems with a single directive: `@loading`.

## Defining the Shape

Let's look at how we can address the first point by using the `@loading` directive. Simply put, the `@loading` directive
is used to describe the desired shape of your loading state. While a network request is pending, the `data` value will contain every
field with `@loading` starting from the top. Let's start off simple and see what happens if we just put `@loading` at the top of
our query like this:

```graphql
query SpeciesInfo($id: Int = 1) {
	species(id: $id) @loading {
		name
		description
		evolutionChain {
			name
			...Sprite_species
		}

		...Sprite_species
		...MoveList_species
		...NavButtons_species
	}
}
```

If you log the result while fetching, then you'll see that `data` looks something like:

```typescript
import { PendingValue } from '$houdini'

{
	species: PendingValue
}
```

First, notice that `species` isn't an object with fields in it. That's because we only put `@loading`
on the `species` field (more on this later). Also, see the value? It might seem a little strange at first, but rather
than using `undefined` or something else, you are given a symbol that you can easily use for comparisons
inside of your component:

```svelte:title=src/routes/[[id]]/+page.svelte&typescriptToggle=true
<script lang="ts">
    import { PendingValue } from '$houdini'

    // ...

    $: species = $SpeciesInfo.data.species
</script>

<Container>
    <Panel slot="left">
        {#if species === PendingValue}
            <Display height={30} loading />
            <Sprite style="flex-grow:1" loading />
            <Display height={120} loading/>
        {:else}
            <Display>
                {species.name}
            </Display>
            <Sprite {species} />
            <Display>
                {species.description}
            </Display>
        {/if}
    </Panel>
    <Panel slot="right">
        {#if species === PendingValue}
            <div class="evolution-chain">
                {#each Array.from({length: 3}) as _, i }
                    <div class="evolution-form">
                        <Number value={i + 1} />
                        <Sprite height={96} loading />
                        <Display height={30} loading />
                    </div>
                {/each}
            </div>
            <div class="row">
                <Display height={400} loading />
                <UpDownButtons disabled />
            </div>
            <div class="row">
                <Button disabled>Previous</Button>
                <Button disabled>Next</Button>
            </div>
        {:else}
            <div class="evolution-chain">
                {#each species.evolutionChain as evolvedForm, i }
                    <div class="evolution-form">
                        <Number value={i + 1} />
                        <Sprite style="height: 96px;" species={node} />
                        <Display>
                            {node.name}
                        </Display>
                    </div>
                {/each}
            </div>
            <MoveList {species} />
            <NavButtons {species} />
        {/if}
    </Panel>
</Container>
```

Since our document contains `@loading`, `data` is no longer `null` when fetching.
It's a small win but it means we can remove the `?` in the definition for `species`. It also means
we don't have to check for `fetching` anymore and can start to unify our loading and final UIs
by sprinkling in `if`s that check for values in our query results.

That being said, if your first thought was "that doesn't seem much different" then you are correct. Having
just a single `@loading` directive at the top of your document is pretty much the same as what we had before. The real
power starts to show when you use it multiple times in the same document. You see,
Houdini will walk down your query and build your loading state as long as it encounters the directive. The deepest fields
that are tagged with `@loading` will be set to the sentinel `PendingValue`.

Let's see this in action:

```graphql
query SpeciesInfo($id: Int = 1) {
	species(id: $id) @loading {
		name @loading
		description
		evolutionChain @loading(count: 3) {
			name
			...Sprite_species
		}

		...Sprite_species
		...MoveList_species
		...NavButtons_species
	}
}
```

<DeepDive title="What is the Shape of This Loading State?">

The shape follows the same rules as before: intermediate objects and lists
will get the appropriate type and the last field tagged with `@loading` gets
set to `PendingValue`. In this case, the user specified the number of elements that
should be added to the loaded state. This means that the shape of data looks something like:

```typescript
import { PendingValue } from '$houdini'

{
    species: {
        name: PendingValue,
        evolutionChain: [
            PendingValue,
            PendingValue,
            PendingValue,
        ]
    }
}
```

</DeepDive>

With this change, `data.species` is **always an object**. We now have to look at one of its fields to
know if we are loading:

```svelte:title=src/routes/[[id]]/+page.svelte
<script lang="ts">
    import { PendingValue } from '$houdini'

    // ...

    $: species = $SpeciesInfo.data.species
</script>

<Container>
    <Panel slot="left">
        {#if species.name === PendingValue}
            <Display height={30} loading />
            <Sprite style="flex-grow:1" loading />
            <Display height={120} loading/>
        {:else}
            <Display>
                {species.name}
            </Display>
            <Sprite {species} />
            <Display>
                {species.description}
            </Display>
        {/if}
    </Panel>
    <Panel slot="right">
        <div class="evolution-chain">
            {#each species.evolutionChain as evolvedForm, i }
                <div class="evolution-form">
                    <Number value={i + 1} />
                    {#if node !== PendingValue}
                        <Sprite style="height: 96px;" species={node} />
                        <Display>{node.name}</Display>
                    {:else}
                        <Sprite height={96} loading />
                        <Display height={30} loading />
                    {/if}
                </div>
            {/each}
        </div>
        {#if species.name === PendingValue}
            <div class="row">
                <Display height={400} loading />
                <UpDownButtons disabled />
            </div>
            <div class="row">
                <Button disabled>Previous</Button>
                <Button disabled>Next</Button>
            </div>
        {:else}
            <MoveList {species} />
            <NavButtons {species} />
        {/if}
    </Panel>
</Container>
```

Things are slightly different now that we have multiple applications of `@loading`.
`data.species` is always safe to use which means our loading value is starting to reflect the final query value
and we can loosen our guards.

However, that's a tiny win compared to what we were able to do with the evolution chain. Here it is
again for quick reference:

```svelte
    <div class="evolution-chain">
        {#each species.evolutionChain as evolvedForm, i }
            <div class="evolution-form">
                <Number value={i + 1} />
                {#if evolvedForm !== PendingValue}
                    <Sprite style="height: 96px;" species={node} />
                    <Display>{node.name}</Display>
                {:else}
                    <Sprite height={96} loading />
                    <Display height={30} loading />
                {/if}
            </div>
        {/each}
    </div>
```

See that `species.evolutionChain` is always safe to iterate over?? This let us pull out all of the repeated
structure and only differentiate the 2 cases where it actually matters. Pretty cool huh?

Houdini makes sure that there is always _something_ we can use to render
and because of how we used `@loading` we can compare our values to `PendingValue` where its most convenient.
If you're still not quite sure how this works please check out the DeepDive above. If it's still confusing, join us
on discord and open a question - we'd love to help. It's also worth mentioning that `3` is the default value for `count`
so it wasn't actually necessary here.

Problem #1 solved. You can use `@loading` to create the most convenient shape for your exact needs. When it falls on
lists, Houdini will even create lists with the appropriate values so you always have something to iterate over. This leaves
us with one more thing to clean up: our route is still duplicating the structure of its sub-components.

## Composing Loading States

So with the first hurdle addressed, the only thing left is to wire up the fragments so that they can handle
their own loading needs. In doing so, our route can stay totally decoupled from the internal structure of the component.

As I'm sure you guessed, this is done with `@loading`. All we have to do is mark the fragment spread with `@loading` and Houdini
takes care of the rest:

```graphql:title=src/routes/[[id]]/+page.gql
query SpeciesInfo($id: Int = 1) {
    species(id: $id) @loading {
        name @loading
        description
        evolutionChain @loading(count: 3) {
            name
            ...Sprite_species
        }

        ...Sprite_species
        ...MoveList_species @loading
        ...NavButtons_species @loading
    }
}
```

```svelte:title=src/routes/[[id]]/+page.svelte
<Container>
    <Panel slot="left">
        {#if species.name === PendingValue}
            <Display height={30} loading />
            <Sprite style="flex-grow:1" loading />
            <Display height={120} loading/>
        {:else}
            <Display>
                {species.name}
            </Display>
            <Sprite {species} />
            <Display>
                {species.description}
            </Display>
        {/if}
    </Panel>
    <Panel slot="right">
        <div class="evolution-chain">
            {#each species.evolutionChain as evolvedForm, i }
                <div class="evolution-form">
                    <Number value={i + 1} />
                    {#if node !== PendingValue}
                        <Sprite style="height: 96px;" species={node} />
                        <Display>{node.name}</Display>
                    {:else}
                        <Sprite height={96} loading />
                        <Display height={30} loading />
                    {/if}
                </div>
            {/each}
        </div>
        <MoveList {species} />
        <NavButtons {species} />
    </Panel>
</Container>
```

Pretty straightforward, right? So what did this take? Well, not much. Here's a rough example of what `NavButtons` looks like:

```svelte:title=src/components/NavButtons.svelte&typescriptToggle=true
<script lang="ts">
    import type { NavButtons_species } from '$houdini'

    export let species: NavButtons_species

    // prettier-ignore

    $: data = fragment(species, graphql(`
        fragment NavButtons_species on Species {
            id @loading
        }
    `))

    $: pending = $data.id === PendingValue
</script>

<div class="row">
    <Button disabled={pending || $data.id <= 1}>
        Previous
    </Button>
    <Button disabled={pending || $data.id >= 151}>
        Next
    </Button>
</div>
```

Just like with the query, the only thing we had to do is use `@loading` on a value that we could
compare against to render our loading state.

<DeepDive title="This is Getting Pretty Repetitive">

If you find yourself wanting `@loading` on every field in your document (fragment or query), you
can put it on the document definition to implicitly add it to every field:

```graphql:title=src/routes/[[id]]/+page.gql
query SpeciesInfo($id: Int = 1) @loading {
    species(id: $id)  {
        name
        description
        evolutionChain {
            name
            ...Sprite_species
        }

        ...Sprite_species
        ...MoveList_species
        ...NavButtons_species
    }
}
```

You can also use the `cascade` argument to attach `@loading` to a field and all of its children:

```graphql:title=src/routes/[[id]]/+page.gql
query SpeciesInfo($id: Int = 1) {
    species(id: $id) @loading {
        description
        evolutionChain @loading(cascade: true) {
            name
            ...Sprite_species
        }
    }
}
```

This implicitly marks `name` and `...Sprite_species` with `@loading` as well.

</DeepDive>

## Final Thoughts

Thanks for making it all the way through this guide! I hope you found it useful and that it illustrated the
power of treating your loading states as a first class concern in your fragments. These examples could be taken
further by breaking the route into separate components with fragments that own each section of the UI and
its loading state and I encourage you to do so in your own application. I think you'll find that being able
to reuse these bits of UI will make your designers happier and your application will look better with less effort.
