It's good practice to start new IT projects by considering how to easily and quickly consume and display data, and one of the first steps is creating or choosing the right API for your business. So why not choose an API that's a universal query language and provides a modern approach to accessing your data sources?

With its growing popularity, you have probably already heard about GraphQL, another great tool that Facebook developers make available to the world in addition to React. GraphQL was developed internally by Facebook in 2012 before being released to the public in 2015.

Advantages of GraphQL
  1.  A single endpoint.
  2.  No more over-fetching. 
  3.  No more under-fetching.
  4.  Display changes in real time.
  5.  Access multiple data sources from a single point.
  6. Front-end teams can easily test their applications by mocking up the required data structures. 
  7.  Services usually respond using JSON,  which is easy to read and debug.
  8.  Works with other JavaScript-based libraries and frameworks, such as Vue, Angular, and others.
  9.  Can be used with any back-end framework or programming language.
GraphQL vs Rest

Let's take a look at the Rest call image below:

null

Image courtesy of How to GraphQL

As How to GraphQL explains, "With REST, you have to make three requests to different endpoints to fetch the required data. You’re also overfetching since the endpoints return additional information that’s not needed."

One solution used in Rest API is query parameters. It works, but it requires complex logic and has no flexibility. Furthermore, working in this way slows the whole process of developing other data endpoints.

How GraphQL Works in the Same Situation

 

null

Image courtesy of How to GraphQL

Much simpler, don't you think?

How it Works

The syntax is simple and easy to understand. Developers who are familiar with JSON will quickly adapt to GraphQL. Look at the image below to see what this query returns.

null

 

 

 

 

 

 

Schema & Type System

GraphQL's Schema Definition Language (SDL) serves as the contract between the client and the server to define how a client can access the data.

BASIC TYPES

    String
     Int
     Float
     ID
     Boolean

OPERATION TYPES

   Queries: are data requests to the server based on your needs.

   Mutations: are used to insert, update, or delete data.

   Subscriptions: push data from the server to the clients who chose to listen to real-time messages from the server.

RESOLVERS

Resolvers provide the instructions for turning a GraphQL operation into data. Resolvers are organized into a one to one mapping to the fields in a GraphQL schema. - Apollo Docs

GraphQL Best Practices

The following recommendations are brief paraphrases of the best practices listed on the GraphQL website

HTTP

Avoid creating a suite of URLs. GraphQL supports this, but having a suite of URLs makes it harder to access GraphQL tools like the IDE, and you will also have other endpoints, which goes against the main idea behind GraphQL.

JSON (with GZIP)

In a production GraphQL service, it's recommended that GZIP compression is enabled. So in client requests, we can set in the header:

Accept-Encoding: gzip

Versioning

As with any other API, you can start versioning your GraphQL Project, but usually you have to do this when you have limited control over the data that is returned or when you have new features.

GraphQL only returns what is explicitly requested, so new capabilities can be added via new types and new fields on those types without introducing a big change in the code.

Nullability

By default, all types in GraphQL are nullable and can go awry in a networked service backed by databases and other services.

Pagination

The GraphQL type system allows for some fields to return lists of values but leaves the pagination of longer lists of values up to the API designer.

Ultimately, designing APIs with feature-rich pagination led to a best practice pattern called "Connections."

Server-Side Batching & Caching

A naive GraphQL service can be very "chatty" or repeatedly load data from your databases. A good way to handle that is to collect multiple requests and later dispatch them in a single request.

A good tool is  Facebook DataLoader.

Some Front-End Clients to Make Your Life Easier
  1. Relay
  2. Apollo Client

 Some advantages: 

         Data fetching
         Caching logic
         Easier pagination

GraphQL Examples for Two Different Scenarios

Below, I will give two very brief examples of GraphQL implementations, one for the flow and the other for the source code.

CONSUMING AND PROVIDING DATA WITH APOLLO/GRAPHQL IN AN ORACLE DATABASE

LP image

Back-End Provider

First, you need to define your endpoint:

const schema = graphqlTools.makeExecutableSchema({typeDefs, resolvers});
    
graphqlAC.use('/graphql', graphql({
        graphiql: true,
        schema
    }));
Second, define your types:
const typeDefs = `
   type Post {
       identifier: Int!,
       title: String!
    },
`
}
Then, define resolvers and operations:
const resolvers = {
        Query: {
            posts(root, args, context, info) {
                return getAllPosts();
            },
       },
    };
Finally, define your business logic implementation method to get data from the Oracle database.
    async function getAllPosts() {
       let sql = 'select * from posts';      
        const result = await database.simpleExecute(sql);
        let allPosts = [];       
        for (let r of result.rows){
            const newTitle = {"identifier": r.IDENTIFIER, "title": r.TITLE};               
          allPosts.push(newTitle);
       }
        return allPosts;
     }

Front-End Consumer

In your React application, you must connect your app component, wrapping it with the ApolloProvider tag:

const client = new ApolloClient({ uri: 'http://localhost:5000/graphql' });
<ApolloProvider client={client}>
<App />
</ApolloProvider>
Then consume data from the GraphQL API with Apollo from a functional component:
const GET_MOTIVO = gql`
{
posts {
identifier
   title
}
}
`
const Apollo = () => (
<Query query={GET_MOTIVO}>
{({ loading, error, data }) => {
if (loading) return <div>Loading...</div>;
if (error) return <div>Error :(</div>;
return data.motivos.map(({ identifier , title }) => (
<div key={identifier}>
<p>{`${identifier}: ${title}`}</p>
</div>
));
}}
</Query>

QRAPHQL WORKING WITH MONGODB

Back-End Provider 

As with the fist scenario, we start by defining an endpoint.

app.use('/graphql', 
graphqlHttp({
schema : graphiqlSchema,
rootValue: graphilResolvers,
graphiql: true
})
);
 Next, we define our Schema, then our Queries.
type Event {
_id: ID!
title: String!
description: String
price: Float!
date: String!
creator: User!
}

type RootQuery{
events: [Event!]!
}
Finally, we define our resolvers.
events: async () => {
try {
const events = await Event.find();
return events.map(event => {
return event;
});

} catch(err) {
throw err;
}
},

Front-End Without a Client

The following example shows how to consume a GraphQL service without a client:

fetchEvents() {
const requestBody = {
query: `
query {
events {
_id
title
date
description
price
creator {
_id
email
}
}
}
`
};

fetch('http://localhost:5000/graphql', {
method: 'POST',
body: JSON.stringify(requestBody),
headers: {
'Content-Type': 'application/json',
}
}).then(res =>{
if(res.status !== 200 && res.status !== 201){
throw new Error ('Failed');
}
return res.json();
}).then(resData => {
const events = resData.data.events;
this.setState({ events : events});
}
}).catch(error => {
console.log(error);
});
}
Conclusion

The main goal of the two different scenarios above is to demonstrate how flexible, powerful, and easy to use your APIs can be with GraphQL. So don't be afraid to use GraphQL in your next project--at least make one MVP to try it out. Be brave!

References/Further Reading:

For references and further reading, I recommend that you check out: 

1. GitHub GraphQL dataloader

2. GitHub relayjs

3. The New York Times - Now on Apollo

4. GraphQL Best Practices

5. React, Relay and GraphQL: Under the Hood of The Times Website Redesign

6. React and GraphQL at the NYTimes

7. Introduction to GraphQL

 


Author

Leandro Rezende Pinheiro

Leandro Pinheiro is a UI Engineer at Avenue Code. In addition to being addicted to web application solutions, he is a movie marathonist and a music lover who enjoys having a good beer by his side.


React Context API

READ MORE

Spring WebFlux: A Quick Start

READ MORE

How to Determine a Performance Baseline for a Web API

READ MORE