Tutorial: Fullstack React Native with GraphQL
Tags: tutorial, graphql, react, javascript
Published: 2019-12-23 09:28:40

---
title: Tutorial: Fullstack React Native with GraphQL
published: true
date: 2018-04-13 00:00:00 UTC
tags: tutorial, graphql, react, javascript
canonical_url: https://blog.hasura.io/tutorial-fullstack-react-native-with-graphql-and-authentication-18183d13373a/
---

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

_Edit notice: This blogpost was updated on 1st March, 2019 for updating the deprecated parts._

## **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.

To build the app, we will be using:

- [React Native](https://facebook.github.io/react-native/)
- [Apollo Client](https://www.apollographql.com/docs/react/)
- [Hasura GraphQL Engine](https://hasura.io/) (for GraphQL backend)
- [Auth0](https://auth0.com/) (for auth)

_Note: We will be using the new_ [_Query_](https://www.apollographql.com/docs/react/essentials/queries.html#basic) _and_ [_Mutation_](https://www.apollographql.com/docs/react/essentials/mutations.html#basic) _components that Apollo introduced in their 2.1.3 release of_ [_react-apollo_](https://github.com/apollographql/react-apollo)_._

## Part 1: Deploying a GraphQL backend

We need a GraphQL backend where we can store the state of our app. We will be using the open source [Hasura GraphQL Engine](https://medium.com/r/?url=https%3A%2F%2Fgithub.com%2Fhasura%2Fgraphql-engine) that gives instant Realtime GraphQL over Postgres.

**Deployment**

- Deploy Hasura GraphQL Engine by simply clicking on the button below.

[![Hasura on Heroku](https://www.herokucdn.com/deploy/button.svg)](https://heroku.com/deploy?template=https://github.com/hasura/graphql-engine-heroku)<figcaption>Click this button to deploy the GraphQL engine to Heroku</figcaption>

- Note the URL of the deployed app. It should be of the form: `myfancyapppname.herokuapp.com`. This is your GraphQL Engine URL.

**Creating the tables**

For storing the user information , we will create a `users` table.

```
users
+--------+-----------------------------+
| column |      type                   |
+--------+-----------------------------+
| id     | serial NOT NULL primary key |
| name   | text NOT NULL primary key   |
+--------+-----------------------------+
```

* * *

Here is the significance of the columns:

- **id** : This is a unique integer that will identify each entry in the `users` table. It is also the primary key of the table.
- **name:** This is the name of the user

The data for this table will be coming from Auth0.

_Note: Setting up Auth0 and integrating with Hasura has already been done and it is beyond the scope of this tutorial._ [_Click here_](https://docs.hasura.io/1.0/graphql/manual/auth/jwt.html#auth0) _for learning how to do it._

For storing our todos, we will need a `todos` table with the following fields.

```
todos
+--------------+---------------------------------------------------+
|    column    |         type                                      |
+--------------+---------------------------------------------------+
| id           | serial NOT NULL primary key                       |
| task         | text NOT NULL                                     |
| is_completed | boolean NOT NULL                                  |
| user_id      | integer NOT NULL FOREIGN KEY REFERENCES users(id) |
+--------------+---------------------------------------------------+
```

Here is the significance of the columns:

- **id** : This is a unique integer that will identify each _todo_. It is also the primary key of the table.
- **text** : This is the to-do task.
- **is\_completed** : This is a boolean flag that marks the task as _completed_ and _pending._
- **user\_id:** This is a foreign key referencing `id` of the `users` table. It relates the todo to its author.

Let us create the above tables in our backend:

- Go to your GraphQL Engine URL in your browser. It opens up an admin UI where you can manage your backend.
- Go to the `Data` section on top and click on “Create Table” and add the aforementioned column names and types.

![](https://blog.hasura.io/content/images/2019/03/image.png)<figcaption>Creating <code>todos</code> table</figcaption>

![](https://blog.hasura.io/content/images/2019/03/image-1.png)<figcaption>Creating <code>todos</code> table</figcaption>

**Table relationships**

As you see above, there is meant to be a foreign-key based relationship between `todos` and `users` . Lets add the foreign key constraint and the relationship. Go to the `Data` tab on top and click on `todos` table. Now, in the modify section, edit the `user_id` column and make it a foreign key. After this go back to the `Data` tab and click on `Track all relations` .

![](https://cdn-images-1.medium.com/max/1000/1*GFlOoTknXkAA_OYkmbBwNA.png)<figcaption>Adding foreign keys</figcaption>

![](https://cdn-images-1.medium.com/max/1000/1*uR2lus1px_M2CpxcNe_HNw.png)<figcaption>Adding relationships</figcaption>

Once you track the relationship, you can make complicated nested GraphQL queries to `https://myfancyapp.herokuapp.com/v1alpha1/graphql` . To try out, go to the `GraphiQL` tab in the console and try making a query.

![](https://cdn-images-1.medium.com/max/800/1*h27UvTXOI7rDXQakCZJ7LQ.png)<figcaption>GraphiQL - An API Explorer</figcaption>

**Table permissions**

In our `todos` table, we want users to CRUD only their own todos. Hasura provides an access control layer for setting up rules to restrict data to specific roles. In this app, we will have only `user` role. Let us set permissions for it.

Go to `/data/schema/public/tables/user/permissions` in your Hasura console and enter the role `user` and allow CRUD in the `user` table only when `x-hasura-user-id` is equal to `id` . This means that Hasura will ensure that a user can CRUD only when the `X-Hasura-User-Id` from the JWT in the header is equal to the `id` of the user that they are CRUDing over.

![](https://cdn-images-1.medium.com/max/800/1*uP8hZXyhXMT5NWPQ_Bc7Jg.png)<figcaption>Setting insert permission for users table</figcaption>

The above screenshot shows the permission condition for `insert` query, add similar permissions for `select` , `update` and `delete` queries.

Similarly, add permissions for `todos` table with a condition: `{ 'user_id': 'X-Hasura-User-Id' }` . This means that a user can CRUD only their own todos.

With this, we have set up our backend. Let us work on React Native now.

### Part 2: Setup React Native Project

We will be using [Expo](http://expo.io) for this tutorial. Get started with a boilerplate project by running:

```
npm install -g expo-cli
expo init Todo
cd Todo
npm start
```

This will create an empty React Native project where `App.js` is the entry point. This `App.js` must maintain a state called `isLoggedIn` which if false, it should renders the Auth screen, else render the the app (currently just `Hello world` . It should also pass `login` and `logout` functions as props to the AuthScreen and the app respectively. The `App.js` should currently look something like:

{% gist https://gist.github.com/wawhal/5950313b1348eb7ec9f99fe14b12a5e2.js %}

### Part 3: Setup Auth

Since we are using JWT, install the package `jwt-decode` from npm.

```
npm install --save jwt-decode
```

Create a directory called `src` at the top level and create another subdirectory in it called `auth`. Inside `auth` , create a file called `Auth.js` and perform authentication with auth0 using Expo’s AuthSession. The `Auth0.js` should look something like this.

{% gist https://gist.github.com/wawhal/09db8d03771f099f35295f553a43abb1.js %}

The above component does the following:

1. Render a button called login pressing which, Auth0 login is performed using Expo’s AuthSession.
2. After the authentication is complete, the session variables are stored in `AsyncStorage` and `isLoggedIn` of the parent component is set to true so that the app is navigated to the app.

Once auth is complete, next, we have to instantiate Apollo client for client side GraphQL.

### **Configuring Apollo Client**

Firstly, 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
```

Create a file called `apollo.js` and export a funtion that accepts a token and returns an instance of Apollo Client. You have to configure the Apollo client with the GraphQL endpoint and the token. (Replace with your own GraphQL endpoint)

```
import { ApolloClient } from 'apollo-client';
import { HttpLink } from 'apollo-link-http';
import { InMemoryCache } from 'apollo-cache-inmemory';
const GRAPHQL_ENDPOINT = `https://myfancyappname.herokuapp.com/v1alpha1/graphql`;
const createApolloClient = (token) => {
  const link = new HttpLink({
    uri: GRAPHQL_ENDPOINT,
    headers: {
      'Authorization': `Bearer ${token}`
    }
  });
  return new ApolloClient({
    link,
    cache: new InMemoryCache()
  })
}
export default createApolloClient;
```

Now create a directory in the `src` folder called `app` and create a file called `Main.js` . This will be the entrypoint of your todo app where you instantiate the Apollo client using the above function and provide it to the children components using `ApolloProvider` . The child component currently is just `TodoList.` We will write this component in the next section.

Before that, we have to insert the user that logged in into the `users` table with an `insert_mutation` using the client. We can do it in the `componentDidMount` of this component itself before setting client in state.

```
client.mutate({
  mutation: gql`
    mutation ($username: String, $userid: String){
      insert_users (
        objects: [{ name: $username, id: $userid}]
      ) {
        affected_rows
      }
    }
  `,
  variables: {
     username: this.props.username,
     userid: this.props.userid
  }
});
```

_Note:_ `gql` _from_ `graphql-tag` _is like a query parser that parses a graphql-string into an AST document that Apollo client understands._

Your `Main.js` should look something like this:

{% gist https://gist.github.com/wawhal/01f703f971a8ce44bbe728ef1a4999f6.js %}

Also modify the render of `App.js` to pass the appropriate flag.

```
render() {
    const { isLoggedIn, userId, username, loading, jwt } = this.state;
    if (loading) {
      return <View><Text>Loading...</Text></View>
    }
    if (isLoggedIn) {
      return (
        <Main
          userId={userId}
          username={username}
          token={jwt}
          logout={this.logout}
        />
      )
    } else {
      return (<Auth login={this.login}/>)
    }
}
```

### **Creating our first Query component**

Lets write our `TodoList` component. We will use Apollo’s Query components to fetch all the todos from the server. Lets see how to use the Query component

The flow goes like:

- `import {Query} from 'react-apollo';`
- `import gql from 'graphql-tag';` graphql-tag is just like a parser that parses a GraphQL query into
- Pass the GraphQL query string as prop to the `Query` component.

```
<Query query={gql`
  query {
    todos {
      id
      text
      is_completed
    }
  }
`}
>
```

- Wrap your custom component inside the `Query` component.

```
<Query query={gql`GRAPHQL_QUERY`}>
  {(data, error, loading) => {
   return (<MyComp data={data} error={error}, loading={loading} />)
  }}
</Query>
```

- `MyComp` in the above component receives the state and response of the GraphQL query.

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

{% gist https://gist.github.com/wawhal/0b6349b38b6c0ad7670c39d85dee7fdd.js %}

The above component simply fetches all the `todos` and renders their text in a FlatList.

### **Writing our first Mutation component**

Mutation components work just like the Query components except, they also provide a mutate function that can be called whenever you want. In case of mutations, we also need to update the UI after the mutation succeeds.

**Insert todos**

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

{% gist https://gist.github.com/wawhal/e09ab01cc2dcc93bd56086d5bef8a3f4.js %}

In the above component, we use the `<Mutation>` component that provides a render prop with a function to insert todo. The Mutation component also takes an `update` prop which takes a function to update the Apollo cache after the mutation success.

Update the render method of the `Main.js` component to render the above Textbox as well.

```
render () {
    if (!this.state.client) {
      return <View><Text>Loading...</Text></View>;
    }
    return (
      <ApolloProvider client={this.state.client}>
        <Textbox
          userId={this.props.userId}
          username={this.props.username}
          logout={this.props.logout}
        />
        <TodoList
          userId={this.props.userId}
          username={this.props.username}
          logout={this.props.logout}
        />
      </ApolloProvider>
    );
}
```

**Update and delete todos**

As of now, we are just rendering the todo text in the FlatList. We also want the ability to mark the todo as complete and to delete the todos. To do this, we will render each todo item as a separate component instead of just the text. In this component, we can have the marking complete functionality and the delete functionality.

Create a file called `TodoItem.js` . It would look something like this:

```
<script src="https://gist.github.com/wawhal/b2bc438c225c6b96064a387655a7b56a.js"></script>
```

The above component again uses the Mutation components and we follow the same flow that we did while inserting todos. If you observe well, you will notice that we have not updated the cache in case of update mutation. This is because, Apollo cache automatically updates the items if it is able to match the `id` of a mutation response with the `id` of an item in the cache.

Finally, update the render method of `TodoList.js` to render the above `TodoItem` in the Flatlist.

```
render() {
    return (
      <Query
        query={FETCH_TODOS}
      >
        {
          ({data, error, loading}) => {
            if (error || loading) {
              return <View> <Text> Loading ... </Text> </View>
            }
            return (
              <ScrollView style={styles.container} contentContainerStyle={styles.container}>
                <FlatList
                  data={data.todos}
                  renderItem={({item}) => <TodoItem todo={item}}
                  keyExtractor={(item) => item.id.toString()}
                />
              </ScrollView>
            )
          }
        }
      </Query>
    )
  }
```

### Wrapping up

We covered the following in this blogpost

- Deployed a GraphQL server in the form of Hasura GraphQL Engine
- Set up tables and permissions
- Set up a React Native project and performed auth using Auth0.
- Set up Apollo client with a GraphQL endpoint and JWT
- Use Apollo’s Query components to fetch todos
- Use Apollo’s Mutation components

We did not:

- Use Hasura’s GraphQL Subscriptions
- Implement a logout button
- Go into styles of React Native. All code snippets are more like pseudo code code snippets.

* * *

[**_Hasura_**](https://goo.gl/X8nFBP) _gives you instant GraphQL APIs over any Postgres database without having to write any backend code._