Tutorial: Fullstack React Native with GraphQL and Authentication

A tutorial to build a React Native to-do app with Apollo’s new Query and Mutation components

Overview

In this tutorial, we will be building a React Native to-do app that helps us add tasks, view them, mark/unmark them as complete and delete them.

Login screen and the to-do list screen

To build the above app, we will be using:

Note: We will be using the new Query and Mutation components that Apollo introduced in their 2.1.3 release of react-apollo.

Setting up the backend

We need a GraphQL backend along with a database and authentication. Therefore, we will use the Hasura platform which has all three. To get a base Hasura project,

$ hasura quickstart base todo-app-backend
  • Activate your backend using a git push:
$ cd todo-app-backend

Creating a table

For our to-do app, we will need a table with the following fields.

todos

+-----------+------------------------------+

|  column   |       type                   |
+-----------+------------------------------+
| id        | serial NOT NULL primary key  |
| task      | text NOT NULL                |
| completed | boolean NOT NULL             |
| user_id   | integer NOT NULL             |
+-----------+------------------------------+

Here is the significance of the columns:

  • id: This is a unique integer that will identify each task. It is also the primary key of the table.
  • task: This is the to-do task.
  • completed: This is a boolean flag that marks the task as completed and pending.
  • user_id: This is the user_id associated with the user that enters the task.

Lets create the above table in our backend:

  • Open the UI console by running the following command from the todo-app-backend directory:
$ hasura api-console
  • Go to the Data section on top and click on “Create Table” and add the aforementioned column names and types.
  • The GraphQL backend is ready once you have created the table. You can try out the queries and mutations in the API Explorer button.

Table Permissions

By default, every table created on the Hasura platform only has admin permissions set on it. This means that only admin users are allowed to fetch and modify data from tables by default.

Every user created using the Hasura paltform’s authentication APIs is given a user role by default. Since we are going to be using the Hasura platform to add authentication to our react-native app, we need to add permissions to the todos table. The permissions should allow users to fetch, add, update and delete their own todos. Fortunately, this also can be easily done on the API Console.

Go to the Data section in the API console and select the todos table on the left panel. You can modify the table permissions in the Permissions tab.

Click on insert and add the permissions as shown below

The above permission means that for every row inserted into this table, the user_id should be the same as the id of the Hasura user who is making the insert request.

Similarly, set permissions for select, update and delete

Note: The columns selected for select permissions are the columns whose value a user should be allowed to fetch from the table. We allow select on all columns. Similarly, the selected columns for the update permission are the columns whose data can be modified once they have been inserted into the table. In this case, we only allow update on completed and task.

Our modelling for the todo app is now complete. Next, we need to figure out authentication for our app.

Authentication

A robust to-do app needs some kind of a login screen. Since auth is not the primary focus of this tutorial, we will be using the React Native Auth Boilerplate that has authentication already implemented along with boilerplate code for a basic React Native app.

Clone the boilerplate to get started. Also, rename your project and cd into it:$ cp react-native-auth-boilerplate/vanilla ./todo-app -r
$ cd todo-app

$ git clone https://github.com/hasura/react-native-auth-boilerplate

Install node_modules related to the the boilerplate:

$ npm install

Also, enter your clustername in theHasura.js file inside the todo-app directory so that authentication is handled by the Hasura platform APIs. (Run $ hasura cluster status from the todo-app-backend directory to find your cluster name)//replace "clustername45" with your cluster name

const clusterName = "clustername45";

Configuring Apollo Client

Let us install the dependencies related to Apollo client. Run the following command from the todo-app directory.

$ npm install apollo-boost react-apollo graphql-tag graphql --save

Next, create an instance of Apollo client in the App. src/AppScreen.js is the entry component, so it is the right place to instantiate the client. We also need to authenticate our requests using the session token. The React Native Auth Boilerplate stores the session token to the AsyncStorage of the mobile device with a key @<clusterName>:myapp. To instantiate a client and add the session information in the request, make the src/Appscreen.js look like this:

Next, we have to connect the Apollo client with our app. To do that, we need to wrap our root component inside ApolloProvider . Your src/AppScreen.js should finally look like:

Writing GraphQL queries and mutations

Lets make a new file called queries.js in the src directory to store all the GraphQL queries and mutations that we need for the app. We will declare the queries as gql strings. gql lets you write your queries with ES2015 template literals and compile them into an AST with the gql tag.

Our queries.js will look like:

Creating our first Query component

Apollo Client recently released the new Query and Mutation components that work somewhat like renderProps. The flow goes like:

  • import {Query} from 'react-apollo';
  • Pass the GraphQL query string as prop to the Query component.
<Query query={gql`GRAPHQL_QUERY`}>
  • Wrap your custom component inside the Query component.
<Query query={gql`GRAPHQL_QUERY`}>
  • MyComp in the above component received the state and response of the GraphQL query.

We will write our TodoListComponent similary. Create a file called TodoListComponent.js in the src directory. Write a TodoListComponent using the Query component, similar to what is shown above. It will look something like:

The above component simply fetches all the todos and renders them in a flatlist.

Writing our first Mutation component

Mutation components work just like the Query components. In case of mutations, we also need to update the UI after the mutation succeeds.

Create a file called AddButton.js and add the following content to it:

Similarly create aDeleteButton.js too.

Finally, we need an update mutation to mark the tasks as completed and incomplete. We will simply make clickable text and render it in the Flatlist.

Create a file called TodoTextItem.js

Wrapping it up

Now, we need to render the TodoTextItem and DeleteButton components with every to-do task in the Flatlist. Go back to TodoListComponent.js and add TodoTextItem and DeleteButton in the Flatlist. The file will finally look like this:

Finally lets put all of these together in an index component called TodoApp.js. TodoApp will have the AddButton that we created, a textbox and a logout button. On logout, we need to reset the Apollo store using resetStore because the queries are cached in the store.

The TodoApp component looks like:

Running the app

  • For android:
$ react-native run-android
  • For iOS:
$ react-native run-ios

Please comment if you have any questions. You can find the complete code for the app we created, in this github repository.


Hasura is an open-source engine that gives you realtime GraphQL APIs on new or existing Postgres databases, with built-in support for stitching custom GraphQL APIs and triggering web hooks on database changes.