DEV Community

Olowu Abraham
Olowu Abraham

Posted on

Exploring Git API: Fetching and Paginating All Repositories, and Displaying Single Repository Pages using React

Step 1: create the Repository component, you can call it anything you want. this is where are are going to call all the GitHub repositories and also perform our pagination.

Respository.jsx.

// Respository.jsx

import React, { useEffect, useState } from 'react'
import Eachrepo from './Eachrepo'
import axios from 'axios'

const Repositories = () => {
const [reps, setReps]= useState([])
const [Error, setError]= useState(null)
const [loading, setLoading]=useState(true)
  //pignate
const [currentPage, setCurrentPage] = useState(1);
const itemsPerPage = 4;
const indexOfLastItem = currentPage * itemsPerPage;
const indexOfFirstItem = indexOfLastItem - itemsPerPage;
const currentItems = reps.slice(indexOfFirstItem, indexOfLastItem);
const totalPages = Math.ceil(reps.length / itemsPerPage);

const handlePageChange = (newPage) => {
  setCurrentPage(newPage);
};

  useEffect(()=>{
    const fetchdata = async()=>{
     try{
       const rep = await axios.get(`https://api.github.com/users/abrahamsegun/repos?per_page=100`);
       const data = await rep.data;
       setReps(data)
       setLoading(false)
     } catch (error) {
       setError(error)
       setLoading(false)
       console.log(`Your code is having this ${error} error`)
     }
    }
    fetchdata();
 }, [])

 if(loading){
  return <div className='loading'>Loading ...</div>
  }
  if(Error){
   return <div>error: {Error.message}</div>
  }
  return (
    <div>
        <Eachrepo handlePageChange={handlePageChange} reps={reps} currentPage={currentPage} totalPages={totalPages} currentItems={currentItems}></Eachrepo>
    </div>
  )
}

export default Repositories
Enter fullscreen mode Exit fullscreen mode

First I imported axois and my react hooks to the component. then I stored my GitHub repositories API inside the reps state.

line 6 and line 24- 26.

//array
=>  const [reps, setReps]= useState([])
//update 
=>  setReps(data)
Enter fullscreen mode Exit fullscreen mode

I handle any errors using the Error state and conditionally render my page with a loading message due to API delays.

Afterward, I implemented pagination for my page from line 10 to 20. The variable names are self-explanatory, but please note that on line 15, reps.length represents my GitHub state, which is updated as per the state defined in line 5.

*Note: *
The handlePageChange function in your code is responsible for updating the currentPage state when called. This function is passed down to the Eachrepo component as a prop.

step 2: Each repo component
I decided to display in Api fetched data in the Eachrepo component .

// Eachrepo component

import React from 'react'
import "../css/eachrepo.css"
import "../App.css"
import {Link} from "react-router-dom"

const Eachrepo = ({handlePageChange , currentItems, totalPages, currentPage, reps}) => {
  return (
    <div className='eachrepo'id='eachrepo'>
      {currentItems.map((each)=>{
        return(
        <div className='singlerepo' key={each.id}> 

         <div id='smallerme'><Link to={`/each/${each.name}`}> <h2>{each.name}</h2>  </Link></div>
            <div className='eachupdate' >
            <p id='smalleru'>{each.language}</p> 
              </div> 
              </div>)
      })}
      <div>
       <div>
        <button onClick={() => handlePageChange(currentPage - 1)} disabled={currentPage === 1}>
        Previous
        </button>
          <span>Page {currentPage} of {totalPages}</span>
        <button onClick={() => handlePageChange(currentPage + 1)} disabled={currentPage === totalPages}>
        Next
        </button>
      </div>
    </div>
    </div>
  )
}

export default Eachrepo
Enter fullscreen mode Exit fullscreen mode

This is where I displayed my repository name called each.name from my GitHub repository array.

The link on link 13 is to link the repository name dynamically to new page which is connected to the Route at App.js to display page path according to the repository name

  <Route path="Repositories" element={<Repositories />}>
           <Route path='each/:repoName' element={<DiplayEachRepo />}></Route>
        </ Route>
Enter fullscreen mode Exit fullscreen mode
<Link to={`/each/${each.name}`}> <h2>{each.name}</h2>  </Link>
Enter fullscreen mode Exit fullscreen mode

Then there is a div to display two buttons to control the pages to be displayed. All the functions were passed as props from the parent component (Respository.jsx),the span tag shows the numbers and you carry out the button actions.

Step 3: Individual GitHub Page.
This is where I consumed my data based on the name of the repository. In GitHub the name of the repository leads to another array which consume here.

DisplayeachRepo.jsx

//DisplayeachRepo

import React, { useState, useEffect } from 'react';
import { useParams } from 'react-router-dom';
import axios from 'axios';
import { Link } from 'react-router-dom';
import '../css/display.css';

const DiplayEachRepo = () => {
  const { repoName } = useParams();
  const [repository, setRepository] = useState({});

  useEffect(() => {
    const fetchData = async () => {
      try {
        const rep = await axios.get(`https://api.github.com/repos/abrahamsegun/${repoName}`);
        const data = await rep.data;
        // const dadada = data.find((r) => r.name === repoName);
        setRepository(data);
      } catch (error) {
        console.log(error);
      }
    };
    fetchData();
  }, [repoName]);

  if (!repository) {
    return (
      <div className='loadingEach'>
        <div>Loading...</div>
        <div>If it persists, please go back</div>

        <Link to='/'>
          <button className='btn'>Go Home</button>
        </Link>
      </div>
    );
  }

  return (
    <section className='bigwahala'>
      <h2>{repository.name}</h2>

      <br />
      <br />
      <ul className='uldisplay'>
        <li>Languages: {repository.language ? repository.language : 'NONE'}</li>
        <li>Stars: {repository.stargazers_count}</li>
        <li>Forks: {repository.forks_count}</li>
      </ul>
      <hr />
      <div className='hr'>
        <ul>
          <div className='issuesdiv'>
            <p>Issues:</p>{' '}
            <p>
              {repository.open_issues_count > 0
                ? `${repository.open_issues_count} open issue(s)`
                : 'No issues'}
            </p>
          </div>
          <div className='visibitydiv'>
            <p> Visibility: </p>
            <p>{repository.visibility}</p>
          </div>
        </ul>
      </div>
      <hr />
      <div className='ButtonGit'>
        <button>
          <Link to={`https://github.com/abrahamsegun/${repoName}`}>Go to GitHub repository</Link>
        </button>
      </div>
    </section>
  );
};

export default DisplayEachRepo;



Enter fullscreen mode Exit fullscreen mode

Clicking on each name in EachRepo will open up the individual API to be consumed here.

The useParams hook provides access to the parameters of the current route. In your case, it extracts the repoName parameter from the URL. For example, if your route is "/repos/:repoName" and the user navigates to "/repos/any-repo", repoName would be equal to "any-repo".

Finally, there is a GitHub link for each of them at line 69 to check the code on GitHub.

Thank you.

Top comments (0)