Hello guys๐๐ผ, today we'd be talking about graphQL and how it works with React. We'd also be looking at a popular library called Apollo that helps handle GraphQL requests in most frontend frameworks including React.
Table Of Contents
- What is GraphQL
- REST vs GraphQL
- Making Requests to REST & GraphQL APIs
- Making GraphQL requests with Apollo
- Should you use GraphQL?
What is GraphQL
GraphQL (publicly released in 2015) is a query language for APIs and server-side runtime for fulfilling those queries with your existing data (as stated on the GraphQL documentation). Simply put, GraphQL is a way of interacting with your APIs that involves using a query language to send requests and the server sending responses based on the query. This query can also be in form of a mutation in cases where we want to edit or update a particular document. GraphQL works with schemas which are simply rules that dictate the type of data we can query or mutate and the queries or mutations that can be performed on them.
REST vs GraphQL
REST (Representational State Transfer) was the de-facto standard (some would argue it still is) for building APIs as it enabled a whole lot of simplicity while using APIs as compared to its predecessors (SOAP and CORBA). With REST:
- Every request is handled independently, therefore, a request must be accompanied with every bit of information needed for the server to successfully process it.
- REST also brought about the use of HTTP verbs: GET, POST, PUT, PATCH, DELETE, OPTIONS, etc
Seems like REST has done a lot of good already, then why, why would we want to leave our good ol' REST for this new (REST was popularised in 2000) tool?
Well, as good as our RESTful APIs are, they have some drawbacks:
Statelessness
This actually seems to fall on both sides of the spectrum as it can be advantageous too. The fact that we don't handle state on the server makes our server lightweight and reduces its complexity but this state management is then pushed to the frontend thereby increasing its complexity.
Security
SOAP APIs are more secure as opposed to REST APIs as they undergo more stringent security protocols but evidently require more management.
Overfetching / Underfetching Data
Say we had an ecommerce app and we're trying to get the reviews of a particular user's product. We'd probably have a route to get the list of users and we could make this route return all products of a particular user as well as the reviews of each product. Whenever we need the names of users only, we will be overfetching data because we'd be getting the products and their reviews.
On the other hand, we could break it down by having a route to get all users, another route to get the list of products owned by a user and one more route to get the reviews of that product. This would be underfetching because we had to make 3 requests to get our desired response.
Lastly, we could have two getUsers
routes with one responding with the list of users only and the other responding with the products and reviews too. Unfortunately, this would break our DRY (Don't Repeat Yourself) rule and might increase the complexity of our server.
GraphQL helps us solve this last issue effortlessly through the use of its query language because we're specifying exactly what we want from the server on every request. REST and GraphQL can be used together on one server but that will also cause an increase in complexity.
Making Requests to REST & GraphQL APIs
Sending requests to both APIs are similar in the sense that they use JSON to send and receive data.
axios({
method: 'get',
url: 'https://jsonplaceholder.typicode.com/todos/1',
// data: {
// firstName: 'Finn',
// lastName: 'Williams'
// }
}).then((resp) => {
console.log(resp.data);
});
The code above is the typical way to send requests to a REST API using the axios
package. The method
stands for the HTTP verb, and data
, the request body we want to send along with the request.
With GraphQL, all requests are POST requests going to a particular route usually /graphql
and the code snippet is like so:
const body = {
query: `query GetProductById($id: String){
getProductById(id: $id){
name
price
imageUrl
}
}`,
variables: {
id: productId
}
}
axios({
method: 'post',
url: 'https://www.mygraphqlserver.com/graphql,
data: body
}).then((resp) => {
console.log(resp.data);
});
We write our query (or mutation) in template literals, and our variables in an object. variables are simply values in our code we want to pass into our query. The keys query
and variables
of our body object must be named like that for our graphQL request to be successful.
Making GraphQL Request with Apollo
Apollo is a library that can be used on the client to communicate with GraphQL servers, serve as a state management library on the client and can also be used to set up a GraphQL server on the backend. When using Apollo on the client (and utilizing it's state management feature) , it sort of combines our GraphQL server schema with the schema we provide it on the client side (the client side schema represents our client side state). When making requests, we then specify in our query if Apollo should check on the client or on the server. We won't be using the state management features of Apollo in this tutorial though.
To get started, create a React App by running
yarn create react-app apollo-app
then install Apollo and GraphQL by running yarn apollo/client graphql
.
Head to the index.js file and paste the code below:
import React from "react";
import ReactDOM from "react-dom";
import { ApolloClient, InMemoryCache, ApolloProvider } from '@apollo/client'
import App from "./App";
const cache = new InMemoryCache()
const client = new ApolloClient({
uri: 'https://mygraphqlserver.com',
cache
})
ReactDOM.render(<ApolloProvider client={client}>
<App />
</ApolloProvider>, document.getElementById("root"));
We simply created the client
passing in the URL of our GraphQL server and cache
. The client
object is then passed as a prop to the ApolloProvider
. This enables us make GraphQL requests in our components with Apollo.
Then in the component where the request is to be made, App.js in this case:
import React from "react";
import { useQuery, gql } from '@apollo/client'
import "./style.css";
const GET_COLLECTIONS = gql`
query GetProductById($id: String){
getProductById(id: $id){
name
price
imageUrl
}
}`
export default function App() {
const {loading, error, data} = useQuery(GET_COLLECTIONS,{
id: productId //Where id is the product id
})
console.log(error,data)
if(loading) return <h1>Loading...</h1>
if(error) return <h1>An Error Occurred </h1>
return (
<div>
<h1>Hello StaBlitz!</h1>
<p>Start editing to see some magic happen :)</p>
</div>
);
}
In the component, we first import useQuery
and gql
. useQuery
helps us to actually make the request while gql
helps us create the query (or mutation). You pass the query as the first argument to the useQuery
function. In cases where you have variables (like we do), you pass them in an object as the second argument to the useQuery
function.
Should you use GraphQL
Well, like most things in software engineering, It depends. GraphQL has grown in popularity since its release mainly due to the problem it solves and probably because it's backed by Meta (Facebook). It has garnered a lot more users and seems to have become a serious opponent but REST is still being used by most companies. My advice will be to play around with GraphQL on side projects cause what do you lose from learning something new ๐๐คท๐ฝโโ๏ธ.
Feel free to comment what you think about GraphQL overtaking REST and any other thing you think I missed in the article. Thanks for reading the article โค. Till we meet again, I remain @the_dro _.