summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorArmand Philippot <git@armandphilippot.com>2022-01-24 14:52:04 +0100
committerArmand Philippot <git@armandphilippot.com>2022-01-24 19:12:06 +0100
commit958569e09071e4bb290f0ec120b4309ae5983d2d (patch)
treebb3e49a7b616ccf0acdef330294d7dbbb7339135 /src
parent368fbbf83b913b90cef9dfbe4288e148d589d033 (diff)
refactor(project): replace repo api call method with hook and swr
Instead of using post slug and an environment variable to fetch repo data, I use the given repo in each project MDX file. It allows me to fetch data from another user/organization if needed. To make it work, I no longer provide the full URL in MDX file. The new format is: "User/repo-slug". I also replaced the fetch method with SWR to improve caching and to avoid React complaining about cleanup useEffect.
Diffstat (limited to 'src')
-rw-r--r--src/components/ProjectSummary/ProjectSummary.tsx41
-rw-r--r--src/pages/projet/[slug].tsx2
-rw-r--r--src/services/repos/github.ts15
-rw-r--r--src/ts/types/repos.ts (renamed from src/ts/types/github.ts)2
-rw-r--r--src/utils/hooks/useGithubApi.tsx23
5 files changed, 45 insertions, 38 deletions
diff --git a/src/components/ProjectSummary/ProjectSummary.tsx b/src/components/ProjectSummary/ProjectSummary.tsx
index 0d00f06..5a4f9c8 100644
--- a/src/components/ProjectSummary/ProjectSummary.tsx
+++ b/src/components/ProjectSummary/ProjectSummary.tsx
@@ -1,36 +1,25 @@
import GithubIcon from '@assets/images/social-media/github.svg';
import GitlabIcon from '@assets/images/social-media/gitlab.svg';
import { t } from '@lingui/macro';
-import { getRepoData } from '@services/repos/github';
import { ProjectMeta } from '@ts/types/app';
-import { RepoData } from '@ts/types/github';
import { slugify } from '@utils/helpers/slugify';
+import useGithubApi from '@utils/hooks/useGithubApi';
import Image from 'next/image';
import { useRouter } from 'next/router';
-import { useEffect, useState } from 'react';
import styles from './ProjectSummary.module.scss';
const ProjectSummary = ({
- slug,
title,
cover,
meta,
}: {
- slug: string;
title: string;
cover: string;
meta: ProjectMeta;
}) => {
const { license, repos, technologies } = meta;
- const [data, setData] = useState<RepoData>();
const { locale } = useRouter();
- const githubUser = process.env.NEXT_PUBLIC_GITHUB_USER;
-
- useEffect(() => {
- getRepoData(slug)
- .then((repoData) => setData(repoData))
- .catch((e) => console.error(e));
- }, [slug]);
+ const { data } = useGithubApi(repos?.github ? repos.github : '');
const getFormattedDate = (date: string) => {
const dateOptions: Intl.DateTimeFormatOptions = {
@@ -87,7 +76,10 @@ const ProjectSummary = ({
<dt>{t`Repositories`}</dt>
{repos.github && (
<dd className={styles['inline-data']}>
- <a href={repos.github} className={styles.repo}>
+ <a
+ href={`https://github.com/${repos.github}`}
+ className={styles.repo}
+ >
<GithubIcon />
<span className="screen-reader-text">Github</span>
</a>
@@ -95,7 +87,10 @@ const ProjectSummary = ({
)}
{repos.gitlab && (
<dd className={styles['inline-data']}>
- <a href={repos.gitlab} className={styles.repo}>
+ <a
+ href={`https://gitlab.com/${repos.gitlab}`}
+ className={styles.repo}
+ >
<GitlabIcon />
<span className="screen-reader-text">Gitlab</span>
</a>
@@ -103,15 +98,17 @@ const ProjectSummary = ({
)}
</div>
)}
- {data && (
+ {data && repos && (
<div>
<dt>{t`Popularity`}</dt>
- <dd>
- ⭐&nbsp;
- <a href={`https://github.com/${githubUser}/${slug}/stargazers`}>
- {t`${data.stargazers_count} stars on Github`}
- </a>
- </dd>
+ {repos.github && (
+ <dd>
+ ⭐&nbsp;
+ <a href={`https://github.com/${repos.github}/stargazers`}>
+ {t`${data.stargazers_count} stars on Github`}
+ </a>
+ </dd>
+ )}
</div>
)}
</dl>
diff --git a/src/pages/projet/[slug].tsx b/src/pages/projet/[slug].tsx
index 82e2ea3..0f3aea9 100644
--- a/src/pages/projet/[slug].tsx
+++ b/src/pages/projet/[slug].tsx
@@ -103,7 +103,7 @@ const Project: NextPageWithLayout<ProjectProps> = ({
<ToC />
</Sidebar>
<div className={styles.body}>
- <ProjectSummary slug={id} title={title} cover={cover} meta={meta} />
+ <ProjectSummary title={title} cover={cover} meta={meta} />
<ProjectContent />
</div>
<Sidebar position="right">
diff --git a/src/services/repos/github.ts b/src/services/repos/github.ts
deleted file mode 100644
index 37400ad..0000000
--- a/src/services/repos/github.ts
+++ /dev/null
@@ -1,15 +0,0 @@
-import { RepoData } from '@ts/types/github';
-
-/**
- * Retrieve repository data from Github by slug.
- * @param repo - The repository slug.
- * @returns {Promise<RepoData>} - The repository data.
- */
-export const getRepoData = async (repo: string): Promise<RepoData> => {
- const user = process.env.NEXT_PUBLIC_GITHUB_USER;
- const api = `https://api.github.com/repos/${user}/${repo}`;
-
- const response = await fetch(api);
-
- return response.json();
-};
diff --git a/src/ts/types/github.ts b/src/ts/types/repos.ts
index 923fb08..7dacacc 100644
--- a/src/ts/types/github.ts
+++ b/src/ts/types/repos.ts
@@ -3,3 +3,5 @@ export type RepoData = {
updated_at: string;
stargazers_count: number;
};
+
+export type RepoAPI = 'github';
diff --git a/src/utils/hooks/useGithubApi.tsx b/src/utils/hooks/useGithubApi.tsx
new file mode 100644
index 0000000..4b0b3b2
--- /dev/null
+++ b/src/utils/hooks/useGithubApi.tsx
@@ -0,0 +1,23 @@
+import { RepoData } from '@ts/types/repos';
+import useSWR, { Fetcher } from 'swr';
+
+const fetcher: Fetcher<RepoData, string> = (...args) =>
+ fetch(...args).then((res) => res.json());
+
+/**
+ * Retrieve data from Github API.
+ * @param repo The repo name. Format: "User/project-slug".
+ * @returns {object} The data and two booleans to determine if is loading/error.
+ */
+const useGithubApi = (repo: string) => {
+ const apiUrl = repo ? `https://api.github.com/repos/${repo}` : null;
+ const { data, error } = useSWR<RepoData>(apiUrl, fetcher);
+
+ return {
+ data,
+ isLoading: !error && !data,
+ isError: error,
+ };
+};
+
+export default useGithubApi;