/svelte-apollo

Svelte integration for Apollo GraphQL

Primary LanguageTypeScriptMIT LicenseMIT

svelte-apollo

Svelte integration for Apollo GraphQL.

Example

The following simple example shows how to run a simple query with svelte-apollo.

<!-- App.svelte -->
<Books />

<script>
  import { ApolloClient } from "@apollo/client/core";
  import { setClient } from "svelte-apollo";
  import Books from "./Books.svelte";

  // 1. Create an Apollo client and pass it to all child components
  //    (uses svelte's built-in context)
  const client = new ApolloClient({
    /* ... */
  });
  setClient(client);
</script>
<!-- Books.svelte -->
<script>
  import { query } from "svelte-apollo";
  import { GET_BOOKS } from "./queries";

  // 2. Execute the GET_BOOKS GraphQL query using the Apollo client
  //    -> Returns a svelte store of promises that resolve as values come in
  const books = query(GET_BOOKS);
</script>

<!-- 3. Use $books (note the "$"), to subscribe to query values -->
{#if $books.loading}
  Loading...
{:else if $books.error}
  Error: {$books.error.message}
{:else}
  {#each $books.data.books as book}
    {book.title} by {book.author.name}
  {/each}
{/if}

API

# query(document[, options])

Query an Apollo client, returning a readable store of result values. Uses Apollo's watchQuery, for fetching from the network and watching the local cache for changes. If the client is hydrating after SSR, it attempts a readQuery to synchronously check the cache for values.

<script>
  import { query } from "svelte-apollo";
  import { GET_BOOKS } from "./queries";

  const books = query(GET_BOOKS, {
    // variables, fetchPolicy, errorPolicy, and others
  });

  function reload() {
    books.refetch();
  }
</script>

<ul>
  {#if $books.loading}
    <li>Loading...</li>
  {:else if $books.error}
    <li>ERROR: {$books.error.message}</li>
  {:else}
    {#each $books.data.books as book (book.id)}
      <li>{book.title} by {book.author.name}</li>
    {/each}
  {/if}
</ul>

<button on:click="{reload}">Reload</button>

Reactive variables are supported with refetch:

<script>
  import { query } from "svelte-apollo";
  import { SEARCH_BY_AUTHOR } from "./queries";

  export let author;
  let search = "";

  const books = query(SEARCH_BY_AUTHOR, {
    variables: { author, search },
  });

  // `books` is refetched when author or search change
  $: books.refetch({ author, search });
</script>

Author: {author}
<label>Search <input type="text" bind:value="{search}" /></label>

<ul>
  {#if $books.loading}
    <li>Loading...</li>
  {:else if $books.error}
    <li>ERROR: {$books.error.message}</li>
  {:else if $books.data}
    {#each $books.data.books as book (book.id)}
      <li>{book.title}</li>
    {/each}
  {:else}
    <li>No books found</li>
  {/if}
</ul>

# mutation(document[, options])

Prepare a GraphQL mutation with the Apollo client, using Apollo's mutate.

<script>
  import { mutation } from "svelte-apollo";
  import { ADD_BOOK } from "./queries";

  const addBook = mutation(ADD_BOOK);
  let title = "";
  let author = "";

  async function handleSubmit() {
    try {
      await addBook({ variables: { title, author } });
    } catch (error) {
      // TODO
    }
  }
</script>

<form on:submit|preventDefault="{handleSubmit}">
  <label for="book-author">Author</label>
  <input type="text" id="book-author" bind:value="{author}" />

  <label for="book-title">Title</label>
  <input type="text" id="book-title" bind:value="{title}" />

  <button type="submit">Add Book</button>
</form>

# subscribe(document[, options])

Subscribe using an Apollo client, returning a store that is compatible with {#await $...}. Uses Apollo's subscribe.

<script>
  import { subscribe } from "svelte-apollo";
  import { NEW_BOOKS } from "./queries";

  const newBooks = subscribe(NEW_BOOKS);
</script>

{#if $newBooks.loading}
  Waiting for new books...
{:else if $newBooks.data}
  New Book: {$newBooks.data.book}
{/if}

# restore(document, options)

Restore a previously executed query (e.g. via preload) into the Apollo cache.

<script context="module">
  import client from "./client";
  import { GET_BOOKS } from "./queries";

  export async function preload() {
    return {
      preloaded: await client.query({ query: GET_BOOKS }),
    };
  }
</script>

<script>
  import { restore } from "svelte-apollo";

  export let preloaded;

  // Load preloaded values into client's cache
  restore(GET_BOOKS, preloaded);
</script>

# setClient(client)

Set an Apollo client for the current component's and all child components' contexts.

<!-- Parent.svelte -->
<script>
  import { setClient } from "svelte-apollo";
  import client from "./client";

  setClient(client);
</script>

# getClient()

Get an Apollo client from the current component's context.

<!-- Child.svelte -->
<script>
  import { getClient } from "svelte-apollo";

  const client = getClient();
</script>