How I Built A Basic Portfolio With GitHub API
Table of contents
After learning the fundamentals of fetching data from an API in ReactJS, I built a basic portfolio page to display my repository data from Github's REST API. This article covers:
the tools I used
how I implemented features
challenges I experienced
For the project, I made use of GET /users/<username>/repos
endpoint, which allowed me to list all public repositories for a specific username. The endpoint gave me the first 30 public repositories from my GitHub profile. This project features these functionalities:
error boundary
nested routes
SEO
pagination
404 page
The Setup
My react project was set up easily with vite in my vscode.
npm create vite@latest
npm create vite@latest my-react-app -- --template react
cd my-react-app
npm install
npm run dev
I used dependencies such as react-router-dom, react-error-boundary, react-helmet-async, react-icons, and react-spinners. The styling of the project was done with vanilla CSS.
Code Development
My approach for fetching the data from the API was with the async/await method. Async functions perform an asynchronous operation in JavaScript. Here's a quick rundown of the code;
useEffect(() => {
getProjects();
}, []);
const getProjects = async () => {
try {
const response = await fetch("https://api.github.com/users/lhorla/repos")
const data = await response.json();
setProjects(data);
setLoading(false);
} catch (error) {
console.log("Something went wrong", error);
}
};
Pagination was implemented to show 10 projects per page, here's my code run down;
const [projects, setProjects] = useState([]);
const [loading, setLoading] = useState(true);
const [currentPage, setCurrentPage] = useState(1);
const [projectsPerPage] = useState(10);
const totalProjects = projects.length;
const indexOfLastProject = currentPage * projectsPerPage;
const indexOfFirstProject = indexOfLastProject - projectsPerPage;
const currentProjects = projects.slice(
indexOfFirstProject,
indexOfLastProject
<Pagination
projectsPerPage={projectsPerPage}
totalProjects={totalProjects}
currentPage={currentPage}
setCurrentPage={setCurrentPage}
loading={loading}
className="pagination"
/>
For nested routes, I install react-router dom, using BrowserRouter to wrap the App.jsx
component in the main.jsx
file
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
<React.StrictMode>
<ErrorBoundary>
<BrowserRouter>
<App />
</BrowserRouter>
</ErrorBoundary>
</React.StrictMode>
);
Error boundary code
class ErrorBoundary extends Component {
constructor(props) {
super(props);
this.state = { hasError: false };
}
static getDerivedStateFromError(error) {
// Update state so the next render will show the fallback UI.
return { hasError: true };
}
componentDidCatch(error, errorInfo) {
// You can also log the error to an error reporting service
console.log(error, errorInfo);
}
render() {
if (this.state.hasError) {
// You can render any custom fallback UI
return (
<div className="errorboundary-container">
<h1>Something went wrong.</h1>
<a href="/">Go back to home</a>
</div>
);
}
return this.props.children;
}
}
404 page
import { useRouteError } from 'react-router-dom';
function NotFound() {
const error = useRouteError();
return (
<div>
<h1>Oops!!!</h1>
<p>Sorry, an unexpected error occured</p>
<p>
<i>{error.statusText} || {error.message}</i>
</p>
</div>
);
}
A major challenge I encountered while building this project was implementing pagination and SEO. I ran into a lot of errors, but all thanks to Google and people I reached out, I was able to fix some of them.
Deployment
The project was deployed with Netlify. It is platform for hosting websites free. All I had to do was create a github repository and commit all my project, then I signed in on netlify.
Conclusion
This is my first react project using an API, react router dom, pagination and error boundary. I'm hoping to modify the project with a better UI and improved responsiveness, you can view the project live here. Feel free to drop your suggestions, I'll love to see the corrections I can make. Thanks for reading!