--- title: Svelte Bindings order: 2 --- # Svelte ## Getting started This "Getting Started" guide covers how to install and set up `urql` and provide a `Client` for Svelte. The `@urql/svelte` package, which provides bindings for Svelte, doesn't fundamentally function differently from `@urql/preact` or `urql` and uses the same [Core Package and `Client`](./core.md). ### Installation Installing `@urql/svelte` is quick and no other packages are immediately necessary. ```sh yarn add @urql/svelte # or npm install --save @urql/svelte ``` Most libraries related to GraphQL also need the `graphql` package to be installed as a peer dependency, so that they can adapt to your specific versioning requirements. That's why we'll need to install `graphql` alongside `@urql/svelte`. Both the `@urql/svelte` and `graphql` packages follow [semantic versioning](https://semver.org) and all `@urql/svelte` packages will define a range of compatible versions of `graphql`. Watch out for breaking changes in the future however, in which case your package manager may warn you about `graphql` being out of the defined peer dependency range. Note: if using Vite as your bundler, you might stumble upon the error `Function called outside component initialization`, which will prevent the page from loading. To fix it, you must add `@urql/svelte` to Vite's configuration property [`optimizeDeps.exclude`](https://vitejs.dev/config/#dep-optimization-options): ```js { optimizeDeps: { exclude: ['@urql/svelte'], } // other properties } ``` ### Setting up the `Client` The `@urql/svelte` package exports a `Client` class, which we can use to create the GraphQL client. This central `Client` manages all of our GraphQL requests and results. ```js import { Client, cacheExchange, fetchExchange } from '@urql/svelte'; const client = new Client({ url: 'http://localhost:3000/graphql', exchanges: [cacheExchange, fetchExchange], }); ``` At the bare minimum we'll need to pass an API's `url` and `exchanges` when we create a `Client` to get started. Another common option is `fetchOptions`. This option allows us to customize the options that will be passed to `fetch` when a request is sent to the given API `url`. We may pass in an options object or a function returning an options object. In the following example we'll add a token to each `fetch` request that our `Client` sends to our GraphQL API. ```js const client = new Client({ url: 'http://localhost:3000/graphql', exchanges: [cacheExchange, fetchExchange], fetchOptions: () => { const token = getToken(); return { headers: { authorization: token ? `Bearer ${token}` : '' }, }; }, }); ``` ### Providing the `Client` To make use of the `Client` in Svelte we will have to provide it via the [Context API](https://svelte.dev/tutorial/context-api). From a parent component to its child components. This will share one `Client` with the rest of our app, if we for instance provide the `Client` ```html ``` The `setContextClient` method internally calls [Svelte's `setContext` function](https://svelte.dev/docs#run-time-svelte-setcontext). The `@urql/svelte` package also exposes a `getContextClient` function that uses [`getContext`](https://svelte.dev/docs#run-time-svelte-getcontext) to retrieve the `Client` in child components. This is used to input the client into `@urql/svelte`'s API. ## Queries We'll implement queries using the `queryStore` function from `@urql/svelte`. The `queryStore` function creates a [Svelte Writable store](https://svelte.dev/docs#writable). You can use it to initialise a data container in `urql`. This store holds on to our query inputs, like the GraphQL query and variables, which we can change to launch new queries. It also exposes the query's eventual result, which we can then observe. ### Run a first query For the following examples, we'll imagine that we're querying data from a GraphQL API that contains todo items. Let's dive right into it! ```js {#if $todos.fetching}

Loading...

{:else if $todos.error}

Oh no... {$todos.error.message}

{:else} {/if} ``` Here we have implemented our first GraphQL query to fetch todos. We're first creating a `queryStore` which will start our GraphQL query. The `todos` store can now be used like any other Svelte store using a [reactive auto-subscription](https://svelte.dev/tutorial/auto-subscriptions) in Svelte. This means that we prefix `$todos` with a dollar symbol, which automatically subscribes us to its changes. ### Variables Typically we'll also need to pass variables to our queries, for instance, if we are dealing with pagination. For this purpose the `queryStore` also accepts a `variables` argument, which we can use to supply variables to our query. ```js ... ``` > Note that we prefix the variable with `$` so Svelte knows that this store is reactive As when we're sending GraphQL queries manually using `fetch`, the variables will be attached to the `POST` request body that is sent to our GraphQL API. The `queryStore` also supports being actively changed. This will hook into Svelte's reactivity model as well and cause the `query` utility to start a new operation. ```js ``` ### Pausing Queries In some cases we may want our queries to not execute until a pre-condition has been met. Since the `query` operation exists for the entire component lifecycle however, it can't just be stopped and started at will. Instead, the `queryStore` accepts a key named `pause` that will tell the store that is starts out as paused. For instance, we may start out with a paused store and then unpause it once a callback is invoked: ```html ``` ### Request Policies The `queryStore` also accepts another key apart from `query` and `variables`. Optionally you may pass a `requestPolicy`. The `requestPolicy` option determines how results are retrieved from our `Client`'s cache. By default, this is set to `cache-first`, which means that we prefer to get results from our cache, but are falling back to sending an API request. Request policies aren't specific to `urql`'s Svelte bindings, but are a common feature in its core. [You can learn more about how the cache behaves given the four different policies on the "Document Caching" page.](../basics/document-caching.md) ```js ... ``` As we can see, the `requestPolicy` is easily changed by passing it directly as a "context option" when creating a `queryStore`. Internally, the `requestPolicy` is just one of several "**context** options". The `context` provides metadata apart from the usual `query` and `variables` we may pass. This means that we may also change the `Client`'s default `requestPolicy` by passing it there. ```js import { Client, cacheExchange, fetchExchange } from '@urql/svelte'; const client = new Client({ url: 'http://localhost:3000/graphql', exchanges: [cacheExchange, fetchExchange], // every operation will by default use cache-and-network rather // than cache-first now: requestPolicy: 'cache-and-network', }); ``` ### Context Options As mentioned, the `requestPolicy` option that we're passing to the `queryStore` is a part of `urql`'s context options. In fact, there are several more built-in context options, and the `requestPolicy` option is one of them. Another option we've already seen is the `url` option, which determines our API's URL. ```js ... ``` As we can see, the `context` argument for `queryStore` accepts any known `context` option and can be used to alter them per query rather than globally. The `Client` accepts a subset of `context` options, while the `queryStore` argument does the same for a single query. They're then merged for your operation and form a full `Context` object for each operation, which means that any given query is able to override them as needed. [You can find a list of all `Context` options in the API docs.](../api/core.md#operationcontext) ### Reexecuting queries Sometimes we'll need to arbitrarly reexecute a query to check for new data on the server, this can be done through: ```jsx ``` We use the `requestPolicy` with value `network-only` so we don't hit our cache and dispatch a refresh, if it updates the data the `todos` will be updated due to our cache updating. ### Reading on There are some more tricks we can use with `queryStore`. [Read more about its API in the API docs for it.](../api/svelte.md#queryStore) ## Mutations The `mutationStore` function is similar to the `queryStore` function but is triggered manually and can accept a [`GraphQLRequest` object](../api/core.md#graphqlrequest). ### Sending a mutation Let's again pick up an example with an imaginary GraphQL API for todo items, and dive into an example! We'll set up a mutation that _updates_ a todo item's title. ```html ``` This small call to `mutationStore` accepts a `query` property (besides the `variables` property) and returns the `OperationResult` as a store. Unlike the `query` function, we don't want the mutation to start automatically hence we enclose it in a function. The `result` will be updated with the `fetching`, `data`, ... as a normal query would which you can in-turn use in your UI. ### Handling mutation errors It's worth noting that the promise we receive when calling the execute function will never reject. Instead it will always return a promise that resolves to an `mutationStore`, even if the mutation has failed. If you're checking for errors, you should use `mutationStore.error` instead, which will be set to a `CombinedError` when any kind of errors occurred while executing your mutation. [Read more about errors on our "Errors" page.](./errors.md) ```jsx mutateTodo({ id, title: newTitle }).then(result => { if (result.error) { console.error('Oh no!', result.error); } }); ``` ## Reading on This concludes the introduction for using `urql` with Svelte. The rest of the documentation is mostly framework-agnostic and will apply to either `urql` in general, or the `@urql/core` package, which is the same between all framework bindings. Hence, next we may want to learn more about one of the following to learn more about the internals: - [How does the default "document cache" work?](./document-caching.md) - [How are errors handled and represented?](./errors.md) - [A quick overview of `urql`'s architecture and structure.](../architecture.md) - [Setting up other features, like authentication, uploads, or persisted queries.](../advanced/README.md)