This page covers how to query and update data. If you're looking for information about local state managemment or ways to combine queries to the server with client-side queries, you can read more about that here.
Falcon comes with Apollo Client for client-side state management when you use
create-falcon-app to generate a new application. Apollo Client will be pre-configured and does not require any additional setup. You can start using it right away.
The short version
If you already know how to use Apollo Client, you pretty much know how to use it with Falcon. If you need a refresher, continue to the long version or the Apollo documentation. We also provide a few additional components you can use.
Fetching and sending data from and to the server
Falcon extends and is compatible with Apollo's standard
Falcon's additional components
Falcon comes with a few pre-defined queries and mutations when you create a project with
create-falcon-app. These are primarily from our
@deity/falcon-front-kit package and can be of great use when starting out with an eCommerce application with an integrated blog.
Something you will see in our optional components is a custom
Query component with the query added as a default prop. This can come in handy if you use the same query in multiple files.
You can also use our wrapper
Query component, which extends Apollo's
Query component. The wrapper component will handle loading and error states for you. You can use our
Query component in the same way you would use the Apollo Client version.
The long version
This will go in-depth about how to use Apollo for managing the client state of your Falcon application.
If you're unfamiliar with GraphQL queries it is recommended to check out this guide.
Fetching data (Query component)
Query API is pretty simple if you're familiar with React and the Render Props pattern.
React will call the render prop function you provide with an object from Apollo Client containing
data properties that you can use to render your UI.
Query component subscribes to the data through an observable. The result is first checked in the Apollo Client cache. If the result isn't in the cache, it will make a request to the server. When the data is received from the server, it will be stored in the cache.
If you need near real-time data you can read more about that in the Apollo documentation.
If you need to notify the user when you are refetching data or if their network status has changes, you can read more about that in the Apollo documentation.
Manually firing a query
Sending data (Mutation component)
Here is a guide about GraphQL mutations if you're unfamiliar with GraphQL mutations or would like a refresher. The
Mutation component uses render props just like the
Query component. If you prefer video, you can also watch this video about the
Mutation component by Sara Vieira.
React will call the render prop function you provide with a mutate function and an object with your mutation result containing loading, error, called, and data properties
The mutate function (
addTodo) optionally takes
update; however, you can also pass in those values as props to the
By default mutated data is not immediately reflected in Query components that depend on that piece of data. This is because the
Query component does not know the
Mutation component has changed the data. The Apollo cache needs to be updated after a mutation.
Sometimes when you perform a mutation, your GraphQL server and your Apollo cache become out of sync. This happens when the update you're performing depends on data that is already in the cache; for example, deleting and adding items to a list. We need a way to tell Apollo Client to update the query for the list of items.
This is where the
update function comes in. The
update function is called with the Apollo cache as the first argument. The cache has several utility functions such as
cache.writeQuery that allow you to read and write queries to the cache with GraphQL as if it were a server.
Note: In case of the
update function, when you call
update internally calls
broadcastQueries, so queries listening to the changes will update. Anywhere else,
cache.writeQuery would just write to the cache, and the changes would not be immediately broadcasted.
See the detailed caching guide by Apollo for more information about cache methods.
The second argument to the update function is an object with a data property containing your mutation result. If you specify an optimistic response, your update function will be called twice: once with your optimistic result, and another time with your actual result. You can use your mutation result to update the cache with cache.writeQuery.
Here's an example from Apollo's documentation:
Not every mutation requires an update function. If you're updating a single item, you usually don't need an update function as long as you return the item's
id and the property you updated. While this may seem like magic, this is actually a benefit of Apollo's normalized cache, which splits out each object with an
id into its own entity in the cache. If you try updating a todo, you'll notice that the UI updates immediately. Even though we don't plan on using the mutation return result in our UI, we still need to return the
id and the property we updated in order for our UI to update reactively.
If you'd like to dive deeper into the Apollo cache's normalization strategy, check out their advanced caching guide.
Loading and error states
In the render prop function, we can destructure
error properties off the mutation result. The
Mutation component also has
onError props in case you would like to provide callbacks instead. Additionally, the mutation result object also has a
called boolean that tracks whether or not the mutate function has been called.
Local state management
Continue reading about managing your local state here.