Creating a Project with GraphQL and Understanding Fragments in GraphQL

Danilo Rivera
5 min readJan 31, 2024

--

If you are new to GraphQL, this post will help you start your first project. And if you have knowledge of GraphQL and want to practice fragments, this post is also for you.

Let’s get started! First, we need our React project and then install these dependencies

npm install @apollo/client
npm install graphql-tag babel-plugin-graphql-tag

Create the file .babelrc

{
"plugins": ["babel-plugin-graphql-tag"]
}

Now, we will be using the GitHub API, so we need to generate our token at this link: https://github.com/settings/personal-access-tokens/new

Now, in our root directory, we will create the apolloConfig.js file where the configuration for our client will go.

import { ApolloClient, InMemoryCache, createHttpLink } from "@apollo/client";

const httpLink = createHttpLink({
uri: "https://api.github.com/graphql",
headers: {
Authorization:
"Bearer YOUR_GITHUB_TOKEN",
},
});

export const client = new ApolloClient({
link: httpLink,
cache: new InMemoryCache(),
});

createHttpLink: Imports the createHttpLink function from @apollo/client and uses it to configure an HTTP link. This link is used to make HTTP requests to the GitHub API.

httpLink: Creates an httpLink object with the GitHub API URL and an authorization header containing your GitHub token.

ApolloClient: Imports from @apollo/client and is used to create an instance of the Apollo Client.

client: Creates an instance of the Apollo Client with the previously configured HTTP link (httpLink) and an in-memory cache (InMemoryCache) to store the results of queries.

In summary, these code lines set up the necessary configuration for the Apollo Client to perform queries against the GitHub API using GraphQL. Make sure to replace "YOUR_GITHUB_TOKEN" with your actual GitHub personal access token.

Now, in our index.js, we import our client to use it throughout the app

import React from "react";
import ReactDOM from "react-dom/client";
import "./index.css";
import App from "./App";
import { ApolloProvider } from "@apollo/client";
import { client } from "./apolloConfig";

const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
<React.StrictMode>
<ApolloProvider client={client}>
<App />
</ApolloProvider>
</React.StrictMode>
);

We create the SearchResults component, which will contain the query and be responsible for displaying it on the screen.

import React from "react";
import { useQuery } from "@apollo/client";
import { gql } from "graphql-tag";
import { REPOSITORY_FRAGMENT } from "./fragments";
import "./SearchResults.css";

const SEARCH_QUERY = gql`
query myOrgRepos($queryString: String!) {
search(query: $queryString, type: REPOSITORY, first: 10) {
repositoryCount
edges {
node {
id
name
owner {
login
}
}
}
}
}
`;

const SearchResults = ({ query }) => {
const { loading, error, data } = useQuery(SEARCH_QUERY, {
variables: { queryString: query },
});

if (loading) return <p>Loading...</p>;
if (error) return <p>Error: {error.message}</p>;


return (
<div className="search-results-container">
<h2 className="search-results-title">Search Results</h2>
<ul className="results-list">
{data.search.edges.map((result) => (
<li key={result.id} className="result-item">
<div className="result-details">
<strong>Repository:</strong> {result.node.name},
<strong>Owner:</strong> {result.node.owner.login}
</div>
</li>
))}
</ul>
</div>
);
};

export default SearchResults;

A GraphQL query named myOrgRepos is defined, taking a variable named $queryString of type String. The query utilizes the search operation in GraphQL to search for repositories on GitHub. The search type is specified as REPOSITORY, and the results are limited to the first 10.

A functional component named SearchResults is defined, which receives a query property. Within the component, the useQuery hook is employed to execute the SEARCH_QUERY. The hook returns an object containing information about the query's state, such as loading (loading), error (error), and data (obtained data).

This way, we obtain the data from the GitHub API

In GraphQL, a fragment is a way to reuse and structure specific fields within a query. A fragment allows you to define a set of fields that can be included in multiple queries without repeating the same field definition in each one. This helps keep the code cleaner, modular, and easy to maintain

So in this case, the repository fields, which are fundamental, might be reused in other queries. Therefore, it works better for me to have those fields in a fragment to reuse the code

For learning purposes, we will create a file called fragments.js. Here, we will create a fragment named RepositoryInfo, which will contain all the fields we need and will be reused

import { gql } from "graphql-tag";

export const REPOSITORY_FRAGMENT = gql`
fragment RepositoryInfo on Repository {
id
name
owner {
login
}
}
`;

Now, we need to import that fragment and use it as follows within our search query

const SEARCH_QUERY = gql`
query myOrgRepos($queryString: String!) {
search(query: $queryString, type: REPOSITORY, first: 10) {
repositoryCount
edges {
node {
...RepositoryInfo
}
}
}
}
${REPOSITORY_FRAGMENT}
`;

The complete code would look like this:

import React from "react";
import { useQuery } from "@apollo/client";
import { gql } from "graphql-tag";
import { REPOSITORY_FRAGMENT } from "./fragments";
import "./SearchResults.css";

const SEARCH_QUERY = gql`
query myOrgRepos($queryString: String!) {
search(query: $queryString, type: REPOSITORY, first: 10) {
repositoryCount
edges {
node {
...RepositoryInfo
}
}
}
}
${REPOSITORY_FRAGMENT}
`;

const SearchResults = ({ query }) => {
const { loading, error, data } = useQuery(SEARCH_QUERY, {
variables: { queryString: query },
});

if (loading) return <p>Loading...</p>;
if (error) return <p>Error: {error.message}</p>;

console.log("data.search", data);

return (
<div className="search-results-container">
<h2 className="search-results-title">Search Results</h2>
<ul className="results-list">
{data.search.edges.map((result) => (
<li key={result.id} className="result-item">
<div className="result-details">
<strong>Repository:</strong> {result.node.name},
<strong>Owner:</strong> {result.node.owner.login}
</div>
</li>
))}
</ul>
</div>
);
};

export default SearchResults;

Now imagine you have another query elsewhere in the code, and you need the same repository fields, but also want to include the URL and description. For that, you could do this, using the fragment and simply adding the new fields.

const SEARCH_QUERY = gql`
query myOrgRepos($queryString: String!) {
search(query: $queryString, type: REPOSITORY, first: 10) {
repositoryCount
edges {
node {
... on Repository {
...RepositoryInfo
url
description
}
}
}
}
}
${REPOSITORY_FRAGMENT}
`;

Result

With this simple example, you can now create your first project using GraphQL and utilize fragments to reuse code. As always, the complete code is here

--

--