Building React Native application
When about to start writing a new React Native application, one of the first things I ask myself is “How to handle the logic within the application, and what tools should I use to communicate with the server?”.
In most cases, I’ve had REST API implemented somewhere and simply exchanged information with HTTP requests. GraphQL is a bit different, and I felt this difference from the very first time I used the technology. If you need simple CRUD functionalities in your application’s server — with GraphQL it’s really easy — you can check my tutorial on Super simple GraphQL server with Hapi.js, MongoDB and a new Apollo Server.or use some GQLaaS solutions such as scaphold.io or graph.cool.
But let’s get back to implementation. At first, I had a hard time understanding the new architecture and using Relay as a GraphQL client. While Relay is a great technology (designed by Facebook itself), and is really performant with GraphQL — it might be a bit confusing for newcomers. It also made me feel like I’ve lost some of my project’s flexibility and reusability of part of the components. For those reasons, I started looking for other solutions to handle communication with my GraphQL server. I found two other popular options — one was a library called Lokka and the other was Apollo.
Within the Apollo project there are two solutions that matched my needs. I then started my journey with the apollo-react and apollo-client libraries. They differ a bit, but both can help us achieve clean and performant code.
Apollo Client
You can imagine apollo-client as a root library, with apollo-react as a kind of extension to it. To start, we need to create an instance of ApolloClient and provide a URL to our GraphQL. I’m used to extracting it to a separate file, so that I can easily use it across the application. It’s a bit different when if you’re using apollo-react, but you’ll see that later. For now, we can just create a simple createApolloClient.js file and set up our client.
And now, depending on our needs we can call the .query() and .mutate() functions which behave like HTTP requests.
Example query:
Example mutation:
apollo-client leaves you a lot of freedom and works with every JavaScript solution you want to use within your app. However, when developing React or React Native apps, you should rather go for apollo-react, since it’s designed for React specifically.
Apollo React — Provider
React version of the Apollo library comes with a component that helps us connect our UI tree to GraphQL data. This component is called ApolloProvider and we can get it from apollo-react directly. You should wrap your main application component in the new provider, and pass client as its prop. Client creation is the same as in the example above, since one library depends on another.
As you can see, it’s super simple to do it this way. In the next steps I’ll show you how to attach data from server to our components.
Apollo React — Queries and Mutations
Thanks to our super-simple setup we can now attach queries to our components very easily. Apollo comes with graphql HOC which helps us provide data to our UI. That way we can attach data to any container or component we like. This approach helps us create very readable components — you can see all the data that your view is using and all the mutation functions you want to call within your view. If you don’t want your file to grow too much, you can consider extracting queries and mutations to another file.
As you can see, we can now access both data and mutations. This example might be a bit silly, but I wanted to show you the simplest solution.
A closer look at queries
In the example above we destructed the data prop to get some information from our query. Now I would like to tell you a bit more about the data prop that is attached to our component after calling a query. It’s a bit more complex than it was in the example above, but with complexity we also gain many handful props and functions inside our component. Things like loading state, errors, refetching and a lot of other stuff we had to take care of.
We can see data from our query here, and some additional helper fields. While I’ll leave QuerySubscription for now I would like to write a bit about other fields that can be really helpful while developing our application.
- loading: determines if our request is pending,
- error: error returned from server if request fails,
- refetch: a function used to send the query to the server again,
- startPolling: a function used to start the refetch interval (refetch requests will be send periodically),
- stopPolling: clears the refetch interval.
Thanks to these functions, developing amazing application becomes super easy and fast.
A closer look at mutations
You already know the .mutate() function attached to our component — we can use it the way we’ve seen above, but we might have a problem with attaching multiple mutations to one component.
Fortunately, graphql HOC accepts options as a second function argument. This way, we can specify the name of a prop attached to our component, and use multiple .mutate() functions.
There are also other ways to clarify our mutations code. One of my favourite options is mapping mutate to props. This way we can have clear functions that accept only data we need, without confusing other contributors with wrapping data with variables object.
Now you can simply call .savePost(title, body) within our component.
Conclusion
Thanks to apollo-client and apollo-react packages we can create very simple and readable next-level applications. It works perfectly with React Native, but you should also consider using those packages when developing a React DOM application. You can dive deeper into Apollo docs to gain a fuller overview on the library. You can also find working examples of using Apollo with React on GitHub.
Mike.