Implement an API fetch of your GitHub portfolio Using React.js

Implement an API fetch of your GitHub portfolio Using React.js

Introduction

API is an important term to all developers. This is because mostly everything about software development revolves around this area. From Getting/requesting data from the server to calling already written code eg DOM API(.getElementById), Array methods API (.filter, .map) and lastly calling of 3rd-party packages.

There are many ways to fetch the Github API of a particular user.

In this article, I will walk you through the steps to build a mini-GitHub page just for your profile.


Prerequisites

This app will be built with React, you don't need to have expert knowledge of React because I will walk you through it. However, the following are needed to get started:

  • Basic API knowledge

  • Basic Javascript knowledge

  • Basic knowledge of git

You also need to install:

  • Nodejs

  • react-router-dom

  • npm


What is API ?

One would quickly think, ‘What is API?’. Well, as the full meaning of the abbreviation suggests, API(Application Programming Interface) is simply any tool that allows us to connect our program to someone else’s program.

It is the interface between the program of the front end with that of the backend.

Definition of Terms

Clients are devices that connect to the internet to get data from somewhere or that make a request. It sends a signal to a server and gets a response.

The server is the computer that accepts this request from clients and then responds may be an HTML page, an image, a file, or plain data

Request entails when a device/client asks for a resource eg data, HTML page, authentication token, or an image. Which requires an internet connection such as data, wifi, or wire connection.

The response is the reply to the request, which contains the resource asked for. It could also contain a response that the client is not authorized to receive the resource.

Getting started

Before we continue, below is the UI of my project home page.

Setting-up

On my Windows terminal, I created a new react-app with the folder name - “Github-app” using the command:

npx create-react-app "Github-app"

Then, I navigated to the new folder using the command:


cd "Github-app"

I proceeded to open the folder in Vscode using the command :

code .

On Vscode, I created other files for various components. such as the Home.js file, Github.svg, Error. js as seen below:

Home.js: In the code, it houses my root component. it serves mainly as my landing page. It displays the UI of the navigation bar, profile picture etc.

Error.js: it displays an error message when a user omits a path.

Nav.js: it has the Navigation bar component.

Repo.js: It houses the fetched API for the repositories’ data.

GitHub API fetch

In the home page file, After importing react. I wrote the “Home” function component. Inside the function, I set the states. I wrote the arrow function for click events and passed in numbers. See the code below.

const [githubData, setGithubData] = useState([]);
  const [githubRepos, setGithubRepos] = useState([]);
  const [page, setPage] = useState(1);
  const [isLoading, setIsLoading] = useState(false);

  const handleClick = (number) => {
    setPage(number);
  };

I wrote next the function where I fetched the GitHub API, providing my GitHub username, next to users. The response.js() method works to change JSON to JavaScript. The .then() method works to allow the code to continue executing pending when the fetch request is completed. Below is the fetch request.

const fetchRepos = () => {
    setIsLoading(true)
    return fetch(`https://api.github.com/users/cassie/repos?page=${page}&per_page=5`)
      .then((response) => response.json())
      .then((data) => {
        setGithubRepos(data)
        setIsLoading(false)
      });
  };
  useEffect(() => {
    fetchData()
    fetchRepos()
    // eslint-disable-next-line
  }, [page]);

Next is where I returned the githubData arranged in a div tag and className selector for styling. I also mapped through and returned the githubRepos wrapped in div tags. I also returned the Previous and Next buttons with an onClick event handler.

Lastly, I exported the Home component as seen below:

return (
    <>
    <Navbar/>
      {
        isLoading ? <p>Loading...</p> :
          <div>
            <div className="container">
              <div className="side-bar">
                <img src={githubData?.avatar_url} className="avatar" alt='my profile' />
                <h1 className="full-name">{githubData?.name}</h1>
                <p className="user-name">{githubData?.login}</p>
                <p className="description">{githubData?.bio}</p>
                <p className="followers">{`${githubData?.followers} Followers ${githubData?.following} Following`} </p>
              </div>
              <div className="main">
                <h1 className="heading">List of all my {githubData?.public_repos} Repositories </h1>
                {
                  githubRepos?.map(repo => {
                    return (
                      <div>
                        <Link to={`/repo/${repo.name}`} className ="get-data">{repo?.name}</Link>
                        <p className="public">{repo?.private ? "Private" : "Public"}</p>
                        <p className="language">Language: {repo?.language}</p>
                        <p className="language">Stars: {repo?.stargazers_count}</p>
                        <p className="language">Forks: {repo?.forks_count}</p>
                        <p className="language">Default Branch: {repo?.default_branch}</p>
                      </div>
                    )
                  })
                }
              </div>
            </div>
            <div className="btn-div">
              <button
                onClick={() => handleClick(page - 1)}
                className="previous-btn"
                aria-label="previous-slide"
                disabled={page === 1}
              >
                Prev
              </button>
              <button
                onClick={() => handleClick(page + 1)}
                className="button-next"
                aria-label="next Slide"
                disabled={githubRepos.length < 5}
              >
                Next
              </button>
            </div>
          </div>
      }
    </>
  );
export default Home;

In Repo.js, I wrote the function where I fetched the API for the content of each Repository and returned the HTML element passing in GitHub repo. I also linked the page to the home page using the “Link to” tag. As seen below:

import React, { useEffect, useState } from 'react'
import { Link, useParams } from 'react-router-dom';

function Repo() {
  let {repoId} = useParams();
  const [isLoading, setIsLoading] = useState(false);
  const [githubRepo, setGithubRepo] = useState({});

  const fetchRepo = () => {
    setIsLoading(true)
    return fetch(`https://api.github.com/repos/cassie202/${repoId}`)
      .then((response) => response.json())
      .then((data) => {
        setGithubRepo(data)
        setIsLoading(false)
      });
  };

  useEffect(() => {
    fetchRepo()
    // eslint-disable-next-line
  }, []);

  return (
    <div className='repo-wrapper'>
      {
        isLoading ? <p>Loading ...</p> :
          <div className ="repo-div">
            <p className ="get-data">Repository: {githubRepo?.name}</p>
            <p className="language">Language: {githubRepo?.language}</p>
            <p className="language">Stars: {githubRepo?.stargazers_count}</p>
            <p className="language">Forks: {githubRepo?.forks_count}</p>
            <p className="language">Default Branch: {githubRepo?.default_branch}</p>
            <div>
            <Link to='/' className = "go-to-repo">Go To Repos</Link>
            </div>
          </div>
      }
    </div>
  )
}

export default Repo

Routing

React Router is a standard library for routing in React. It enables the navigation among views of various components in a React Application, It also allows changing the browser URL, and keeps the UI in sync with the URL.

With React Router, a page does not refresh when you navigate to another page.

To get started, install the react-router-dom version 6 in the terminal with the command:

npm install react-router-dom@6

In the App.js file, import reacts, import BrowserRouter as Router, Route, and Routes from react-router-dom. Also, import the various components into the App.js file. Then create the routes. As seen below

import React from "react";
import { BrowserRouter as Router, Route, Routes } from "react-router-dom";
import Repo from "./Repo";
import Home from "./Home";
import Error from "./Error";
import "./App.css";


 function App() {
      return (
        <Router>
          <Routes>
            <Route exact path="/" element={<Home />} />
            <Route exact path="/repo/:repoId" element={<Repo />} />
            <Route exact path="*" element={<Error />} />
          </Routes>
        </Router>
      );
    }



export default App;

The extra feature I added:

I added a navbar with logo and nav items.

I created a Nav-bar file and imported ReactComponent as a logo into the Nav-bar file. Then, I created a navigation component that returned the various navigation items in list forms. As seen below

import { ReactComponent as Logo } from './Github.svg'

const Navbar = () => {
  return (
    <nav className ='nav-bar'>
      <div className='github-logo'>
        <Logo/>
      </div>
      <div>
        <ul className='nav-item'>
          <li>
            <a href="/">Home</a>
          </li>
          <li>
            <a href="/blog">Blog</a>
          </li>
          <li>
            <a href="/projects">Projects</a>
          </li>
          <li>
            <a href="/about">About</a>
          </li>
          <li>
            <a href="/contact">Contact</a>
          </li>
        </ul>
      </div>
    </nav>
  )
}

export default Navbar

Lastly, I styled the elements in the App.css

@import url("https://fonts.googleapis.com/css2?family=Poppins&display=swap");
body {
  margin: 0;
  padding: 0;
  font-family: "Poppins", sans-serif;
  color: #343a40;
  background: #ffff;
  line-height: 1.5;
}
.github-logo{
  width: 10px;
}
.heading{
   color: #297373;
   margin-bottom: 80px;
}
.container{
  display: flex;
  padding: 3rem
}
.get-data{
  color: #2b2b30;
  font-size: 1.5rem;
  font-weight: 900;
}

.side-bar {
  margin-right: 5rem;
  text-align: center;
  background: #FEF7E5;
  height: 400px;

}
#input{
  padding: 5px 100px;
  border: 0.5px solid #6c7075; 
  border-radius: 2px;
}
.avatar{
  width: 100px;
  border-radius:50px;
}

.Error-container {
  text-align: center;
  margin: 200px;
}

.btn-div {
  text-align: center;
}

button {
  margin-left: 0.5rem;
  background-color: #297373;
  padding: 0.5rem 1rem;
  border-radius: 4px;
  border: none;
  color: white;
  cursor: pointer;
  margin-bottom: 5rem;
  }

  button:disabled,
  button[disabled] {
    border: 1px solid #999999;
    background-color: #cccccc;
    color: #666666;
    cursor: auto;
  }

  .repo-wrapper {
    display: flex;
    justify-content: center;
    align-items: center;
    align-content: center;

}

.repo-div {
  text-align: center;
  margin: 50px;
}
.nav-bar{
  background: #FEF7E5;
}

.nav-bar{
  display:flex;
  justify-content: space-between;
}
.nav-item{
  display: flex;
  justify-content: space-between; 
}

ul,li{
  list-style: none;
  padding : 5px;
  text-decoration: none;
}

ul,li,a{
  text-decoration: none;
  color:rgb(29, 28, 28);
  font-size: 18px;
}
.public{
  color: #297373
}
.language{
  line-height: 0.5;
}
.full-name{
  font-size: 1.5rem;
}
.user-name{
  line-height: 1.5;
}
.description{
  line-height: 1.0;
  font-size: 15px;
  overflow-wrap: break-word;
}
.followers{
  line-height: 1.0;
  font-size: 14px;
}

.go-to-repo{
  margin-left: 0.5rem;
  background-color: #297373;
  padding: 0.5rem 1rem;
  border-radius: 4px;
  border: none;
  color: white;
  cursor: pointer;
  margin-bottom: 5rem;
}

Conclusion

These are the basic steps I took in implementing a simple GitHub app using React. I likewise fetched GitHub API and used react-router-dom to navigate to different page components.

Attributions

Credit: geeksforgeesk.com