Want To Know How To Fetch Your GitHub Portfolio From GitHub API? Here Is How

👉Table Of Content

  • Objectives

  • Prerequisite

  • Getting started.

  • GitHub API Fetch

  • Error Boundary

  • 404 Error

  • SEO Optimization

  • Deployment

  • Conclusion

Hello there!

If this is your first time visiting my blog, it’s also my first time visiting my blog too🤣. So, we are all welcome.

Just like the quote from Benjamin Franklin:

"Tell me and I forget, teach me and I may remember, involve me and I learn."

In this article, I will be sharing the process I took in fetching my GitHub profile from GitHub API. This task was given to me by Alt School Africa.

See below a snapshot of the task:

Objectives

By the end of this write-up, you would be familiar with:

  • How to implement a GitHub API fetch of your portfolio

  • How to implement a GitHub API fetch of random users' portfolios.

Before we move on, let us take a look at the overview of the finished GitHub portfolio finder.

GETTING STARTED

I know you are as excited as I am to jump right into it, but before we do that, listed below is the list of technology, dependencies, and languages used for this project.

  • Windows pc

  • VS code

  • ReactJS

  • Cascading style sheet(css)

  • React-router-dom

  • React-paginate

  • Mui material

  • Framer-motion

  • React-icons.

PRERESIQUITE

To fully grasp the concept being shared today, you need to be familiar with ReactJS. So, take a pause and check out this beginner's course👉 Learn ReactJS for free.

Are you back? or you are already a senior dev? 🤣 😂

Now, let’s get started...

Installation

On my windows terminal, I created a project folder named GitHub, and created react app using the code snippet below:

npx create-react-app github-profile-finder
cd github-profile-finder
npm start

and cleaned up my react app, removing files that I would not be needing.

Folder Structuring

I needed to display five pages, so I created a folder called pages in the src folder, created five folders in it and five files following the naming pattern below.

  • Landing Page

  • Home page

  • Repos page

  • A page to show 404 error(Resume page)

  • A page to show the error boundary is working(TestError page).

Okay, let's not ignore the elephant in the room😂 😂. There is a difference between a home and a landing page because I know it crossed your mind.👇

Home page: A home page is a webpage that serves as the starting point of a website.

landing page: A landing page is a page where a visitor land after clicking on an ad.

Issokay, let's get back.

Added to each folder was an additional file for styling. I used the CSS module styling and normal CSS styling.

Next, I created a component folder that contains files such as:

  • Logo

  • Navbar

  • useFetch etc.

Routing

After structuring my pages and component folders, I routed my pages using react-routers. Before you ask😃 , React-router enables navigation amongst the view of various components and allows changing the browser's URL whilst keeping the UI in sync with the URL. If you truly asked what react-routers are used for, please take a pause again and check out this course👉 Learn react-routing.

But to help you understand better, the first thing I did before routing was to install the react-router.

npm install react-router-dom

Then, I imported the router into my app.js file. see the snippet below👇👇

import { BrowserRouter as Router, Routes, Route } from "react-router-dom";
import "./App.css";
import Home from "./Pages/Home/Home";
import Repos from "./Pages/Repositories/Repos";
import Contact from "./Pages/ErrorTesting/Contact"
import ErrorBoundary from "./Components/Errors/ErrorBoundary";
import ErrorPage from "./Pages/404ErrorPage/ErrorPage";
import RepoContent from "./Components/RepoContents/RepoContent";
import Landing from "./Pages/LandingPage/Landing";

export default function App() {
  return (
    <BrowserRouter>
            <Routes>
            <Route path="/" element={<Landing/>} />
              <Route path="home" element={<Home />} />
              <Route path="/repos" element={<Repos />} />
              <Route path="/repos/:content" element={<RepoContent />} />
              <Route path="/contact" element={<Contact />} />
              <Route path="*" element={<ErrorPage />} />
            </Routes>
        </Router>
        </Route>
      </Routes>
    </BrowserRouter>
  );
}

Next, I used Link element to link to all the internal paths of the app that needed to be linked. see the snippet below👇

<Link to="/home">Home</Link>
          <Link to='/repos'>Repos</Link>
          <Link to='/testerror'>Testerror</Link>
          <Link to='*'>Resume</Link>

Github API Fetch

I had to go straight to YouTube to learn a thing or two about how to go about this. but not to worry, I will share my knowledge with you. just be calming down.

So, we all remember the almighty asynchronous function(async/await, promise, callbacks) in JavaScript abi? That is what is used to fetch data from Github API. Here is a lecture on YouTube for people saying “which one is this again”. Learn Asynchronous Functions.

Are you done? or you are already an agba dev😂 ?

Let’s continue,

Personal Data

See below the GitHub API link where we can get all the data we need from our GitHub profile.

const url="https://api.github.com/users/PreyeO"

After the users, you then add your GitHub username.

Now to fetch the data needed I used useState() to set the data to the state I needed it to be in. let's just jump into the code snippet I am sure you would understand better.

import React, {useState, useEffect} from "react";

const useFetchData = (url) =>{

   const  [data,setData ]= useState([])
   const  [error, setError] =  useState(false)
   const[isLoading, setIsLoading] = useState(false)


   async function fetchData() {
    setIsLoading(true)
    const res = await fetch(url);
    res
      .json()
      .then(res => setData(res))

      .then(isLoading => setIsLoading(false))
      .catch(error => setError(error.message));
  }
  useEffect(() => {
    fetchData();
  }, []);
        return  {data, isLoading, error} 
}
export {useFetchData}

There are different ways of using asynchronous functions and I explored two methods. you will get to see the other method pretty soon.

Before you ask, I also used useState() to set the states for when I get an error and when the data is loading.

Finally, I made the fetched data available to all the components/pages that I needed it.

At this point, if you log out your data in your console, you would see various data but since I needed specific information like(repository list) etc. I used the map method to map through.

Yes oo, the JavaScript map not the World map. see the code snippet below👇

const ReposData = () => {
 let datas= useContext(UserFetchData);

const [pageNumber , setPageNumber] =useState(0)

const reposPerPage = 3;
const pageVisited = pageNumber * reposPerPage;
const displayReposData = datas.slice(pageVisited, pageVisited + reposPerPage)
const pageCounter= Math.ceil(datas.length/reposPerPage);
const changePage =({selected}) =>{
  setPageNumber(selected)
 }

 return (
    <Fragment>
    <div className='repos-container'>
        {datas && displayReposData.map(item =>
        <div  key={item.id} className='repos-card'>
          <div className='repos-name'>
          <h5>Name:</h5> 
          <h1>{item.name}</h1>
          </div>
          <div className='repos-btns'>
          <Link to={`${item.id}`}><button>more</button></Link>
          </div>
        </div>
       )}
      </div>
     </Fragment>
  )
}
export default ReposData

From the code snippet above, I received the data that has been fetched and mapped through it to get the list of repositories in my GitHub profile. I displayed three items per page and since I had more than one page of repositories, I used react-pagination to flip through the list.

Then I added a button to view more content of each repository clicked on. To get more content, I used nested routing with useContext(). see below👇

 <Route path="/repos/:content" element={<RepoContent />} />

This was done in my app.js file.

Then I received the created context where I needed to display more content from the repository list.

const RepoContent = () => {
 const { content } =useParams()
 const datas = useContext(UserFetchData)
 const repoInfo = datas.find((item) =>item.id === parseInt(content))
 return (
    <>
        <div className="repo-name">
            <h5>Name:</h5>
            <h1>{repoInfo?.name}</h1>
          </div>
          <div className="repo-description">
            <h5>Description:</h5>
            {repoInfo?.description}
          </div>
          </>
          )
          }

At this point, I congratulated myself because I had done 80% of the work.

Error Boundary

I wrapped my routes in an error boundary and also threw an error in my test error page to display that the error boundary was working. Click the link to learn more about error boundaries.

404Error

I created a page to display a 404 error. Users get redirected to this page whenever they enter the wrong URL.

SEO optimization & Accessibilty

I installed dependencies like(react-helmet, react-document-title and react-helmet,-async) to help with Seo optimization and accessibility. Checked my website's accessibility & optimization status using chrome browser. Click the link to learn more about SEO and Accessibility.

Next, to share my beautiful work with the world and my tutors at Alt School Africa, I had to deploy my app.

Deployment

I ran the code snippet below on my timeline.

npm run build

Then I used vercel to create a link to view. I also deployed it to my GitHub.

Voila!!! I was done. ..

Oh well, so I thought.

I was recently given a holiday challenge to update the app. see below

When I saw it, I screamed OMOO, me? a writer? but that’s how to learn sha.

After I had taken a good look at what I had done previously, I decided to add a new feature.

Random Users

I also wanted users to find random GitHub users' profiles once they have a username. so, a fetched new set of data from github API using this URL:

const Baseurl="https://api.github.com/users"

The difference here is, there was no username added after the users.

Remember when I said I used two different methods in fetching API? here is the second:

const Welcome = () => {
  const [users, setUsers] = useState();
  const baseUrl = "https://api.github.com/users";
  const user = useRef("");

  const findUser = async () => {
    if (user.current.value !== "") {
      const { data } = await axios.get(baseUrl + "/" + user.current.value);
      setUsers(() => [data]);
      user.current.value = "";
    }
  };
  useEffect(() => {
    findUser();
  }, [setUsers]);

Here, installed and used axios to fetch data and also gave it a condition. If a value(username) was entered, the username should be added to the baseurl link when fetched.

Then I fetched the particular information I needed. see code below

{users && users.map((user, idx) => user?.login && (
      <motion.div key= {idx} className={classes.users_card}animate={{ x:0}} initial={{x:-1000}}transition={{type:"tween", duration:1}}>
        <img src={user?.avatar_url} alt={user?.login} />
        <h2>{user?.login}</h2>
        <div className={classes.btn_content}>
        <button>
            <span>{user?.public_repos}</span>
            <h4>Repositories</h4>
          </button>

To add some funkiness😎 , I installed, framer motion for some animations because that’s how I roll.

Click the link below to explore the finished work.👇

👉GitHub Profile Finder

Conclusion

“What we learn to do, we learn by doing”- Thomas Jefferson.

I cannot over-emphasize how learning by doing help. I know it helped me because I can now fetch data from any API without struggles after I completed this task.

Also, I am now a technical writer. You feel me?

Thank you for reading up and I hope you also learnt a thing or two.