How to Use the GitHub API to List and set up pagination for a single user Repositories with React.

How to Use the GitHub API to List and set up pagination for a single user Repositories with React.

As a software engineer, you probably use GitHub quite often, be it as part of your day job, while working on your solo projects, or when contributing to open source.

GitHub is one of the best ways to collaborate on software and discover new projects using Git, the popular Version Control System (VCS). It's safe to say that GitHub is a huge part of the Open Source Software movement that is continually pushing the bounds of technology as we know it by helping developers contribute to more projects and network with other developers.

In this article, you will learn how to use the GitHub API to fetch user information and list out their repositories while also setting up client-side pagination and routing with React.

Prerequisites

  • Web browser

  • DevTools

  • npm installed

  • Reactjs installed

  • Familiarity with React.JS and its extensions such as react-router, react-dom and react-helmet. However, if new to the world of React here is a quick view of how to get started.

Setting up React Application

Below is a simple guide to setting up a react application and also some dependencies used in this project.

npx create-react-app my-app
cd my-app
npm run dev

Note that the " my-app" can be any name of your choice.

Setting up a React Router

React Router is a standard library for routing in React. It enables the navigation among views of various components in a React Application, allows changing the browser URL, and keeps the UI in sync with the URL. It has a simple API with powerful features like lazy code loading, dynamic route matching, and location transition handling built right in. To install React Router, below is a guide to be executed in the project terminal.

npm install react-router-dom@6

Fetching data from GitHub API

Understanding how to consume a rest API is very essential.

As a quick refresher, a REST API is an API that maps a resource to an endpoint. Resource, in this case, means any piece of data necessary for an application to function. For instance, a list of users resource(s) could be mapped to a /user endpoint. For this article, we will be consuming the Github API to get a user's detail and specifically my GitHub profile.

Using Fetch to make an API request in react

Fetch API is a web standard that is implemented in all major browsers to allow for making network requests in a standardized way.

To get my GitHub profile information, the API below would be used.

https://api.github.com/users/achele

Open the GithubPortfolio.jsx file and import some React hooks:

import { useState, useEffect } from "react";
import { GoMarkGithub, GoStar, GoRepo, GoRepoForked, GoOrganization, GoLocation, GoMention } from "react-icons/go"
import{FaTwitter} from "react-icons/fa"

We need to store the response (or error, if any) from calling the API in React state. Initialize two state variables:

export default function GithubPortfolio() {
  const [page, setPage] = useState()
  const url = "https://api.github.com/users/achele"
  const { loading, data } = useFetch(url)
  console.log(data)

Furthermore, We need to query the REST API endpoint when The GithubPortfolio component is mounted and for that, we’ll use the useEffect hook: By using this Hook, you tell React that your component needs to perform a function after rendering. React will remember the function passed, and call it later after performing the DOM updates.

useEffect(()=>{
    const fetchData=async()=>{
      setLoading(true)
  try {
        const res =await fetch(url)
        const doc = await res.json()
        setLoading(false)
        setData(doc)
  } catch (error) {
      setLoading(false)
      handleError(error);
  }
    }
    fetchData()
  },[url])
  return{loading,data}
}

To make my code reusable, a component was created to handle the useEffect. Here, two states were initialized

const [loading,setLoading]=useState(false)

const [data,setData]=useState([])

Also, another component was initialized to fetch a list of all my repositories

export default function Repositories() {
  const [repos, setRepos] = useState([]);
  const [page, setPage] = useState()
  // const handleError = useErrorHandler();
  const total = 6
  const url = `https://api.github.com/users/achele/repos?                                   page=${page}&per_page=5`
  const { loading, data } = useFetch(url)
  console.log(data)

  return (
    <HelmetProvider>
      <Helmet>
        <title>Achez Github Repositories</title>
        <meta name="description" content="list of Achez Repositories"       />
      </Helmet>


      <NavBar />
      <main>
        <div className="flex repos">
          <GoRepo className="repo-icon"/>
        <h4>Repositories</h4>
          </div>
        {loading && <p className="loading">loading</p>}
        {data && data.map(details => <li key={details.id} className="repoList-card ">
          <section className="flex star">
                <div>
            <div className="flex">
              <h3>{details.full_name}</h3>
              {details.private ? (<h4> Private</h4>) : (<h4> Public</h4>)}
            </div>

            <div className="repo-info">
              {details.language ? <p>🟢{details.language}</p> : (<p>🟢null</p>)}
              <p> Updated {" "}
                {formatDistance(subDays(new Date(details.updated_at), 3), new Date(), { addSuffix: true })}
              </p>
            </div>
          </div>

            {details.stargazers_count > 0 && (
              <div className="flex">
                <GoStar/>
                <p>Starred</p>
              </div>
            )}
            {details.stargazers_count === 0 && (
              <div className="flex">
                <GoStar/>
                <p>Star</p>
              </div>
            )}
          </section>

          <Link to="repo" state={{ details: details }}>See more...</Link>
          <hr />
        </li>

        )}

Implement Pagination

Decide on the number of records to be displayed per page and the number of pages. I decided on a total number of 6 and a single page of 5. Also, I thought of keeping track of the page number, the user is on. The states were created.

export default function Repositories() {
  const [repos, setRepos] = useState([]);
  const [page, setPage] = useState()
  const total = 6
  const url = `https://api.github.com/users/achele/repos?                                   page=${page}&per_page=5`

displaying output in the return statement, note that the codes must be wrapped in React fragments or a div.

<div className="btn-container">
        <button disabled={page <= 1} onClick={() => setPage(prev => prev - 1)}>prev</button>
        <p>{page}</p>

        {Array.from({ length: total }, (value, index) => index + 1).map((doc) => <button onClick={() => setPage(doc)} key={doc}>{doc}</button>
        )}
        <button disabled={page >= 6} onClick={() => setPage(prev => prev + 1)}>next</button>
    </div>

Implementing Nested Route

Nested Route is the ability of a react project to have multiple components rendered on the same page, As the word implies a nested route is a route that is nested inside another route, that is, a route in a route, the structure of the implemented nested route is as follows:

 <Route path='repositories' element={<Repositories />}>
    <Route path='repo' element={<Repo />} />
 </Route>

From the above example, the nested Route has the name "Repo" and it is rendered inside the "Repositories" route.

Conclusion

GitHub is a significant part of the day-to-day working lives of many software engineers. GitHub provides one of the nicest RESTful APIs out there. It's easy to get started with, follows good standards, and is, generally speaking, well-documented.

In this post, I've walked you through the process of using the GitHub API to list a user's repositories such as having a design in mind, understanding the various features that will be implemented, getting react started on your editor and importing all necessary dependencies. furthermore, having a folder and file structure, and setting up pagination.

Thanks for reading...