Hasura and React
If you are reading this then it means that you’re probably on your way to know about Hasura and React. Well if that’s the case then you just landed at the perfect location. You might be having all sorts of questions like, “What’s graphql?”, “What’s Hasura?” or more importantly, “Why are we using it?”. Well, fear not everything will be cleared by the time you complete reading this blog. So let’s get started!
This tutorial assumes that you have basic knowledge of React framework. If you are total new to React, I would suggest going through the hello world app of React first before continuing further.The code samples given in as you follow are for main relevant part only, if you intend to copy the code then make sure to import relevant libraries and components also and export the Component created. Otherwise you can take a look at the code repository for this blog.
Hasura is a PaaS with BaaS components. PaaS stands for platform as a service. It allows developers, IT professionals, and business leaders to develop, test, and deploy the next generation of applications in the cloud in a secure, cost-effective manner that speeds time to market and increases competitive advantage.
BaaS stands for Backend as a service. It is a model for providing web app and mobile app developers with a way to link their applications to backend cloud storage and APIs exposed by back end applications while also providing features such as user management, push notifications, and integration with social networking services.
GraphQL is a query language for APIs and a runtime for fulfilling those queries with your existing data. GraphQL provides a complete and understandable description of the data in your API, gives clients the power to ask for exactly what they need and nothing more, makes it easier to evolve APIs over time, and enables powerful developer tools.
The Hasura GraphQL Engine is an extremely lightweight, high performance product that gives you instant realtime GraphQL APIs on a Postgres database. This can be used to quickly build new applications on Postgres or fast-track the move to GraphQL for existing applications on Postgres.It comes with a UI that lets you create and view tables on your database and make GraphQL queries using the embedded GraphiQL interface.
We will be creating a simple todo app which lets a user sign up or login and then manage todos by creating them, marking them as complete or deleting them if neccessary. User will also be able to see his all todos. Visit https://reacthasuratodo.herokuapp.com/ to see a demo of what we will be building.
Deploy your Hasura GraphQL engine to a server which will be used as an endpoint to make queries. Setting up a Hasura GraphQL takes atmost 1 minute. It can be easily deployed to Heroku via its one click deploy to heroku method. Click here to deploy your Hasura GraphQL Engine to a heroku server. Give your heroku app a name and click on deploy app.Your Hasura GraphQL UI will be live at appname.herokuapp.com
Hasura One Click Deploy to Heroku
To secure your Hasura graphql server, add an environment variable HASURA_GRAPHQL_ACCESS_KEY
on Heroku and keep its value to something you can remember. This access key will be asked whenever you try to login on the Hasura Graphql server.
2. Install node and npm in your system.
curl-sL https://deb.nodesource.com/setup_8.x | sudo bash -sudo apt install nodejs
The above command installs both node and npm in your system.
On Windows:Download the relevant package from here and install it.
3. Installing create-react-app (I’ll be using yarn instead of npm)
yarn global add create-react-app
This installs create-react-app globally on your system.
Create a new react app using create-react-app reacthasuratodo
On successful completion of the command, you will see a similar output as in the image. Now open your code editor in the react app directory just created.
Setting up a React app
Change your terminal present working directory to react app directory and run yarn start
. Server will start and you should be able to see a welcome to react screen on http://localhost:3000. This means your react app is running fine.
Live React app
I’ll be using react-bootstrap
package for the styling so install the package using yarn add react-bootstrap
. Make sure to add the stylesheet in /public/index.html
. Complete documentation for react-bootstrap package can be found here.
auth0 is a universal authentication & authorization platform.
Including auth0 in your react app includes the following steps:1. Sign up on https://auth0.com and create a new application.2. Adding a callback url in auth0 console.3. Creating an Auth class.4. Creating history.js5. Creating a Callback component6. Creating routes7. Changing App.js to include auth urls8. Rendering routes instead of App js.
Sign up on https://auth0.com and create a new application for your react app. Provide a relevant name to your auth0 application and headover to settings tab to configure it with your react app.In settings tab under Allowed Callback Urls
add http://localhost:3000/callback
as it will be the callback url on dev environment after authentication completes.
Now install auth0 in your react app by executing yarn add auth0-js
.auth0 has a great react quick start documentation written on their website to include auth0 in your react app.
Create a new file in src/Auth/
as Auth.js
. We’ll be creating an Auth
class which will handle the authentication.
Copy your auth0 clientID
from your auth0 application and paste it in Auth.js
. If you are following from auth0 docs then make sure to add localStorage.setItem('sub', authResult.idTokenPayload.sub)
in setSession()
function and localStorage.removeItem('sub', authResult.idTokenPayload.sub)
in logout()
function. This will store the user id in local storage.
history.js
Create a file history.js
and make its content as in image. Also change App.js
to include login, logout and home buttons.
Auth.js and App.js
Create a callback.js
component which will be shown to user when authorisation is completed.Create a routes.js
to include different routes on which different components will be shown and a route on which authorisation will take place.The content for all the files can be found on auth0 react quick start documentation.
There are 3 different types of queries in graphql, query, mutation and subscription. GET queries are completed by query while insert, delete and update queries are completed by mutation. Subscription listens to any change in event happening, for instance if a new entry is added to table then through subscription it can be notified. This prevents using a GET query all over again.
Create a new table on Hasura API Explorer named todos
. It will have the following fields:1. todo_id: Integer (auto increment)2. todo_text: Text3. todo_mark: Boolean4. todo_user: Text
Creating a table on Hasura
Add table permissions so that every user can access only its data.
role
user.insert
chose with custom checks
Select todo_user
as the field, make it _eq
to X-HASURA-USER-ID
select
chose with same checks as ----
and select all columns for access.update
chose with same checks as ----
and give access only to todo_mark
column.delete
chose with same checks as ----
.
Writing queries in graphql is easy, specify the table name then the fields you want to be in the response. If you want to do selective search then where and order_by can be provided after the table name specification.
A sample query to get all the values in todos table is as follow:
query {todos{todo_idtodo_texttodo_marktodo_user}}
general format for a query is:
query query_name {table_name (where, orderby or pagination expression)]{table fields in response}}
Mutation consists of Insert, Update and Deletions.General format for writing a mutation query is
mutation mutation-name {mutation-type_table-name (expressions to identify row and changing data)affected_rows}
A simple insert query for todos table will look like this:
mutation {insert_todos(objects: [{todo_text: "Complete react app",todo_user: "auth0|20390123821398"}]){affected_rows}}
A simple update query for todos table will look like this:
mutation {update_todos(where: {todo_id: {_eq: 1}}_set: {todo_mark: true}){affected_rows}}
A simple delete query for todos table will look like this:
mutation {delete_todos(where: {todo_id: {_eq:1}}){affected_rows}}
Now we are ready to create the frontend using react and query the db to create and utilise todos.
We’ll be using React Apollo Client to make interact with graphql server and make queries in React. Install apollo client using npm install apollo-boost react-apollo graphql --save
or yarn add apollo-boost react-apollo graphql
.
There will be the following main components:1. One parent component wrapping all the components in apollo provider component.2. GetTodos component to display all the pending todos to the user.3. AddTodos component to add a todo.4. MarkTodo component to mark a todo as completed.5. DeleteTodo component to delete a todo.6. GetAllTodos component to fetch all the todos created till now for a user.
Home.js
The parent component.This component will act as a parent component for all other components, we’ll wrap the child component in an ApolloProvider
which will enable us to use apollo client to make graphql queries in the complete app. ApolloProvider requires a client
prop with a ApolloClient
object. This allows us to make authorised requests. Import ApolloClient from apollo-boost and ApolloProvider from react-apollo. Create a ApolloClient object as followsTo use user authentication, pass the user access token in the headers as Authorization. This will let the Hasura know which user is sending a request to the graphql server. A separate authentication webhook needs to be deployed to allow token authentication. Deploy the webhook to heroku or any other service. It’s easy to deploy using heroku one click deploy. After that configure the HASURA_GRAPHQL_AUTH_HOOK
environment variable in your Hasura Server to your deployed webhook url. Use /auth0/webhook
for auth0 authentication.
Home.js
2. GetTodos
will fetch all the incomplete todos from the database and display them to the user. This component requires the use of React Apollo’s Query component. We first need to write a graphql query to fetch all the incomplete todos from todos table. The method to write a query remains the same as explained above. In react, you need to enclose that query in gql``
. gql is imported from graphql-tag which let the apollo client know that the text enclosed within this text is a graphql query. To keep the code clean, we’ll create a queries.js
and write all the graphql queries in it.
get incomplete todos query
We’ll use this query to fetch all the incomplete todos. In GetTodos component, we’ll be using Apollo’s Query Tag. Create a Apollo Query and pass the graphql query in it as a query
prop. A function inside the Query component will check for the query’s current state (loading), error if present and the data on completion. The data will have all the todos in it, we’ll just iterate over the data and display the relevant content to the user. There should be an option to mark the todo as completed or delete the todo, so we’ll create those components and render along side the data recevied. Finally after all the todos are rendered we’ll give the user an option to add a new todo, we’ll create an AddTodo component for the same and render it next to the Todos shown to the user.
GetTodos component
3. AddTodo component will be used to send an insert request to the hasura graphql server to add a new todo entry in the database. This component will require the use of graphql’s mutation request and Apollo’s Mutation Component.
Query to insert a new todo
Here we will be using variables in the mutation query which will be received from Apollo’s Mutation component. This component will consist of a form which will take the todo_text input from the user and send that to the mutation query as a variable. Create a Mutation component and pass the name of graphql query in mutation prop. Inside a mutation is a function with 2 arguments, first one being the type of mutation and second being an optional data. Insert type of mutation requires todo_text and todo_user as a variable. Any extra data to be sent along the query is included in a dictionary. All the variables are included in a dictionary with variable name as key and its value as dictionary. This variable dictionary is assigned to a variables key in the extra data dictionary. Mutation changes the state of the database, this means if we add a new todo to the database then it should be shown to the user in the list of incomplete todos. This is achieved by refetchQueries. refetchQueries is a list of dictionaries with each dictionary containing the name of query to execute on mutation completion. We’ll refetch all the todos whenever a new todo is added to the database.
AddTodos Component
4. MarkTodo component will be used to send an update request to the database for a particular todo to change its todo_mark value from false
to true
.
Mutation Query for marking a todo as completed
In the MarkTodo component, Create a Mutation component and pass the name of graphql query in mutation prop. MarkTodo component is similar to AddTodos except that AddTodo inserts a new entry while MarkTodo updates an exisiting entry in the database.
Pass the id of todo as a variable to update mutation so that the todo_mark value can be changed in the database. Refetch all the todos on mutation completion.
MarkTodo Component
5. In the same way as MarkTodo, we’ll create a DeleteTodo component. This will allow a user to delete the todo completely from the database. Everything will be same as in MarkTodo except that we’ll use delete_todos as type of mutation.
Query to delete a todo
DeleteTodo Component
6. Finally we’ll create a GetAllTodos component to show users all the todos he has created till now. It will consist of both completed and non completed todos. This component will use a GET query on the todos table and we’ll order the todos by most recently created non completed todos first. Using conditional rendering in react we can style the incomplete todos and completed todos differently.
GetAllTodos Component and Query
Run the server using yarn start
. Head over to http://localhost:3000 to test your app.
And that’s it, it’s that easy to create a React Todo App with Hasura Graphql Engine. You can extend it to include more features and a better look and feel. Deploy your react app to Heroku or any other hosting service so that everyone over the internet can use it.
You can find the source code for this blog here.
Anupam-dagar/react-Hasura-todo_A react todo app using Hasura Graphql engine. Contribute to Anupam-dagar/react-Hasura-todo development by creating an…_github.com
Keep Coding!!!
Useful Resources used while creating the todo app:1. Hasura GraphQL Engine Documentation2. React Apollo GraphQL Documentation3. Auth0 React Quickstart4. Official GraphQL Documentation
My name is Anupam Dagar. I am an undergraduate student at the Indian Institute of Information Technology, Allahabad (A Centre of Excellence in Information Technology established by Ministry of HRD, Govt. of India), pursuing my B.Tech degree in Information Technology.
I love creating and learning new things when I don’t have an overhead of college assignments. I love to code in Python and JavaScript. I am an opensource contributor and currently a GitHub Campus Expert in India.