Building a GraphQL Apollo Client in React.
» What we are Building?
-
So basically we are going to build a app that uses a public GraphQL API to fetch data related to the specific country.
-
So I’ll just give you a quick overview of what we will need in the code. There are going to be two components; the first is the country list component;
- and the second is when we click on the “Click” button which takes us to another link there you are going to have data related to that particular country.
So let’s start by writing the code in our React application.
» Create a new React Project
- Then create a new react app by running the command:
npx create-react-app your-app-name
- Once, your application is created open it into the VS code
» Set up base project.
- In the index.js file, remove all of this code and will just leave this.
- Let’s first start by installing the @apollo/client package that we will need. In the terminal run the command:
npm i @apollo/client
A Note: I’m first going to provide the full code for the specific file, and then explain it. So that it can get easy for you. :)
This is the full index.js file code, till here.
// full index.js file code
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import { ApolloProvider, ApolloClient, InMemoryCache, HttpLink, gql }
from '@apollo/client';
const cache = new InMemoryCache();
const link = new HttpLink({
uri: 'https://countries.trevorblades.com/'
});
const client = new ApolloClient({
cache,
link
});
client.query({
query: gql`
query {
country(code: "IN") {
code
name
}
}
`
}).then(result => console.log(result));
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<ApolloProvider client={client}>
</ApolloProvider>
</React.StrictMode>
);
-
Back to the index.js file, we are going to import ApolloProvider, ApolloClient, InMemoryCache, and HttpLink from the ‘@apollo/client’ we just installed.
-
We’re starting by creating an in-memory cache for our Apollo Client.
-
Next up, we’re setting up an HTTP link to our GraphQL endpoint. Just like this.
-
Now, let’s bring it all together by creating an instance of Apollo Client.
const client = new ApolloClient({
cache,
link
});
- And then We also want to make a GraphQL query to fetch information about a specific country, let’s say, India. So for that, we have to first import gql.
import { gql } from '@apollo/client';
-
And then we call the gql query to fetch the information of the country like its code and its name. Don’t forget to add the template literal symbol “`” after gql. And at last, we console log the result.
-
Moving on, we’re creating a React root for rendering our application.
const root = ReactDOM.createRoot(document.getElementById('root'));
- And now, We utilize ApolloProvider to envelop our entire app, by providing the Apollo Client instance (client) to all components in the component tree via React context.
root.render(
<React.StrictMode>
<ApolloProvider client={client}>
</ApolloProvider>
</React.StrictMode>
);
-
So, what we did here is, we created a GraphQL query to fetch information about a specific country, and we logged it to the console. Now, kickstart the server by executing the command npm start, and the server will start on port 3000. Here let’s inspect this page and check the console to see if the country has been successfully logged.
-
So here in the console, we have this object that has country data and inside it, we have our country code and name present of the country for which we provided the country code.
» Add Query to App.js file
- Now let’s begin with our App.js file. This is the full code, of App.js file till here,
//App.js full code
import React from 'react';
import { gql, useQuery } from '@apollo/client';
const QUERY = gql`
query {
country(code: "US") {
name
code
}
}
`;
function App() {
const { loading, error, data } = useQuery(QUERY);
return (
<div>
{loading && <h1>Loading....</h1>}
{error && <h1>Error: {error.message}</h1>}
{data && (
<>
<div >
<h1><i>Countries List</i>🚀</h1>
</div>
<hr />
{/* <div>
<CountriesList /> --> yet to create
</div> */}
</>
)}
</div>
);
}
export default App;
-
We start by importing gql and useQuery hook from apollo client library. These are part of the Apollo Client library which are used for working with GraphQL queries.
-
Then we declare a GraphQL query using the gql template literal. This query fetches the name and code of the country with the code “IN”. We’ll execute this query using the useQuery hook.
-
And then Inside the App function, we use the useQuery hook to execute the GraphQL query (QUERY). The hook returns an object with properties like loading and error.
-
If the query is still in progress (loading), a loading message will be displayed.
-
If an error occurs during the query, an error message will be returned, displaying the error message.
-
And if the query was successful and there were no errors, the component will render an h1 heading with the text “Countries List”
-
It will also render a CountriesList component (which we will create shortly) responsible for displaying a list of countries.
-
This is what you will observe:
» CountriesList Component
- Let’s now begin creating our components. In the src directory, create a folder named components Inside it, create a CountriesList.jsx file.
This is the full code for CountriesList.jsx file:
import React from 'react';
import { Link } from 'react-router-dom';
import { gql, useQuery } from '@apollo/client';
const COUNTRIES_LIST = gql`
query {
countries {
code
name
}
}
`;
const CountriesList = () => {
const { loading, error, data } = useQuery(COUNTRIES_LIST);
return (
<div>
{loading && <h1>Loading....</h1>}
{error && <h1>Error: {error.message}</h1>}
{data && (
<div>
{data.countries.map((country) => (
<div key={country.code}>
<h3>{country.name}</h3>
<button>
<Link to={`/country/${country.code}`}>
Click for more Information</Link></button>
<hr />
</div>
))}
</div>
)}
</div>
);
};
export default CountriesList;
-
And in the file: We start off by Importing necessary dependencies.
-
Then we import Link from react-router-dom. The Link component is used to create navigation links in a React application. With this we can navigate between different views or pages without triggering a full page reload.
-
We need to insatll this react-router-dom package So in terminal run the command:
npm i react-router-dom
-
Next, define a GraphQL query using the gql template literal. This query fetches the code and name of all countries.
-
And now we declare the CountriesList functional component: Inside which we have The useQuery hook which is used to execute the GraphQL query (COUNTRIES_LIST). The hook returns an object with properties like loading, error, and data.
-
The component will help us returns different content based on the query status.
-
If loading is true, it displays a loading message. If an error occurs during the query, it will displays an error message. If data is present that means (the query is successful), it maps over the array of countries in data.countries and renders a list.
-
For each country, we displays: The country’s name and a button containing a Link to navigate to a detailed view of the country.
-
Now that we have made the CountriesList component and exported it, let’s now import it into the App.js file
-
So in app.js file, import the CountriesList component at the top.
//App.js file
import CountriesList from './components/CountriesList';
-
And now when we look at port 3000 it renders nothing. Why is it so, because we still haven’t defined routes for different components.
-
In index.js file:
//index.js
import { BrowserRouter, Route, Routes } from 'react-router-dom';
-
Then we have to define different routes for different components. We have created just a single components that is CountriesList and we have declared in the App.js file. The main page.
-
So down here, we declare BrowserRouter component which is the top-level component provided by React Router and enables client-side routing. This should wrap your entire application to enable routing functionality.
//index.js file
// Define routes
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<ApolloProvider client={client}>
<BrowserRouter>
<Routes>
<Route exact path='/' element={<App />} />
<Route exact path='/country/:country_id' element={<Country />} />
</Routes>
</BrowserRouter>
</ApolloProvider>
</React.StrictMode>
);
- Then we declare Routes component that is used to define the routes within our application. We then have Route Components. Here this Route component is defined with the exact prop (path='/':) which means it will only match if the path is exactly ‘/’. The path prop specifies the URL path, and the element prop specifies the component to will be rendered when the path matches. In this case, it renders the App component. And now when we save the file, and go back to port 3000 you will have the list of the countries. But when we click on the button nothing happens because we haven’t created a country component yet which takes over to a country detail page. So let’s do that now.
» Country.jsx Component
- In the components folder, create a Country.jsx file. Inside it we start by importing neccessary components and hooks.
//Country.jsx file full code.
import React from 'react';
import { gql, useQuery } from '@apollo/client';
import { useParams } from 'react-router-dom';
const Country = () => {
const { country_id } = useParams();
const QUERY = gql`
query GetCountryDetails($country_id: ID!) {
country(code: $country_id) {
code
name
native
flag: emoji
capital
continent {
name
}
currency
}
}
`;
const { loading, error, data } = useQuery(QUERY, { variables: { country_id } });
if (loading) {
return <p>Loading...</p>;
}
if (error) {
return <p>Error: {error.message}</p>;
}
if (!data || !data.country) {
return <p>No data found for country with ID {country_id}</p>;
}
const { name, native, flag, capital, continent, currency } = data.country;
return (
<div>
<h1>{name} Details</h1>
<h3>Country Name: {name}</h3>
<p>Capital: {capital}</p>
<p>Currency: {currency}</p>
<p>Continent: {continent.name}</p>
<p>Native: {native}</p>
<p>Flag: {flag}</p>
</div>
);
};
export default Country;
-
We import the useParams hook from the react-router-dom library. The useParams hook is used to access the parameters of the current route. Basically, in our code we will use it to get the country_id from the URL.
-
Then we call useParams hook to get the country id parameter from the current route.
-
Now, use the useQuery hook to execute the GraphQL query, passing the country_id parameter using the variables option.
-
Then we also check if there is no data or if the country property in the data is falsy. If true, it returns a message indicating that no data was found for the specified country ID.
-
we then Destructures the relevant properties from the country object in the fetched data.
const { name, native, flag, capital, continent, currency } = data.country;
-
If everthing was correct, it will render the details of the country using the properties obtained from the GraphQL query.
-
So now that we are done with this compoent too. One thing that we are left to do is define route for the country component.
-
So in index.js file, import the country component at the top. And define its route down here. Just like this.
<Route exact path='/country/:country_id' element={<Country />} />
-
Save the file and now when we click on the button it takes us to the country detail page.
-
Click on any country button and it definately takes us to its detail page.
And That’s it! You’ve successfully used grpahql api with apollo client in react.
Thank You and Happy coding!😊