Version: 1.1.0

@Query

The @Query property wrapper loads the data for a GraphQL query when a SwiftUI view is rendered.

A query will usually map one-to-one to a screen of your app. The query can fetch all of the data needed to render that screen in one roundtrip to the server, using @Fragments to provide the data that each child view needs.

Example#

private let query = graphql("""
query ToDoListQuery {
list(id: "abc") {
items {
text
}
}
}
""")
struct ToDoList: View {
@Query<ToDoListQuery> var query
var body: some View {
switch query.get() {
case .loading:
Text("Loading...")
case .failure(let error):
Text("Error: \(error.localizedDescription)")
case .success(let data):
List(data?.list?.items ?? [], id: \.id) { toDoItem in
Text("\(toDoItem.text)")
}
}
}
}

Parameters#

  • O: A type parameter (surrounded in <>) for the type of the query operation to run. The type will be generated by the Relay compiler with a name matching the operation name in the GraphQL query. The Relay compiler will enforce that the operation name is <FileName>Query.
  • fetchPolicy: (optional) The policy for how to fetch data for the query. Valid options are:
    • .networkOnly: (default) Don't use cached data from the store, and show a loading state until data is fetched from the network.
    • .storeAndNetwork: Load any available cached data from the store first, then fetch the current data from the network and update the view when it's loaded.
    • .storeOrNetwork: Load cached data from the store if possible. If any data is missing or any data has been marked invalid in a mutation updater, fetch the current data from the network.
    • .storeOnly: Load the cached data from the store. Do not make a network request, even if the data in the store is incomplete. Only use this if you're sure that the data you need will be in the store already when your view is rendered.

Property value#

The @Query property will have a value with a get function for retrieving the current state of the query:

func get(
_ variables: O.Variables,
fetchKey: Any? = nil
) -> Result

The get function returns already fetched data for the query and/or starts fetching new data, and returns a Result value describing the current state of the data.

  • variables: The variables that your query accepts as input. The values usually come from other properties like @State on your view, if you have any.
  • fetchKey: An optional arbitrary value that can be used to trigger a refetch of the query's data manually. If you pass in a fetch key that doesn't match the one that was passed in the last time the view was rendered, the query's data will be refetched.
enum Result {
case loading
case failure(Error)
case success(O.Data?)
}

A Result is returned by get to indicate the state of query.

  • loading: The query is currently fetching the data it needs. You should show some kind of loading/progress indicator in your UI.
  • failure(Error): The query failed to fetch the data it needed. You can present an error in your UI, optionally using the attached Error for more detailed information.
  • success(O.Data?): The query has the data it needs. The attached structure will have fields that match the shape of the GraphQL query. Note that it's possible for the query to succeed but have nil data, so you need to handle that case, usually by not showing a view at all.

Convenience API for getting query results#

The Relay compiler will generate some nicer extensions to the @Query API that make it easier to pass variables to query.get.

If your query does not take in any variables, you'll get a variant that looks like this:

func get(fetchKey: Any? = nil) -> Result

If your query does take in some variables, you'll get a variant that allows you to pass them as individual arguments, rather than requiring you to create a variables structure. For example, if a query has $id and $name variables, it will have a get method that looks like this:

func get(
id: String,
name: String,
fetchKey: Any? = nil
) -> Result