Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use React Query #19

Merged
merged 3 commits into from
May 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
# Code Review Tool

## Getting Started
1. Set the correct Node version via `nvm use`
2. Start the Firebase Emulators via `npm run dev`
3. In another Terminal, start the React development server by running `npm start` within the `hosting` directory
- In order to authenticate locally, you will need to use `127.0.0.1` rather than `localhost`

## Project Guidelines

### React Query Usage
We use the [React Query](https://tanstack.com/query/latest/docs/framework/react/overview) library for handling caching and synchronisation of our API calls. For consistency, we use the format `[<service-being-called>, <endpoint>, <parameter>]` for our [query keys](https://tanstack.com/query/latest/docs/framework/react/guides/query-keys) (for example: `["github", "repositories", "example-user"]`). We ask that you keep the implementation of [query functions](https://tanstack.com/query/latest/docs/framework/react/guides/query-functions) slim, placing most the logic in the service layer.
30 changes: 25 additions & 5 deletions hosting/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions hosting/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"version": "0.1.0",
"private": true,
"dependencies": {
"@tanstack/react-query": "^5.34.1",
"@types/node": "^16.18.96",
"@types/react": "^18.3.0",
"@types/react-dom": "^18.3.0",
Expand Down
28 changes: 13 additions & 15 deletions hosting/src/components/pages/HomePage.tsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,21 @@
import React, { useState, useEffect } from "react";
import { useQuery } from "@tanstack/react-query";
import { useUser } from "../../hooks/useUser";
import { useGitHub } from "../../hooks/useGitHub";
import { IGitHubUser } from "../../interfaces/github/IGitHubUser";
import { githubService } from "../../services/GitHubService";
import { IGitHubRepository } from "../../interfaces/github/IGitHubRepository";

export function HomePage() {
const [user] = useUser();
const [request] = useGitHub();
const [repositories, setRepositories] = useState<any[]>([]);
const { data: gitUser } = useQuery({
queryKey: ["github", "users", user?.providerData[0].uid],
queryFn: async () => githubService.getUserById(+user!.providerData[0].uid),
enabled: !!user
});

useEffect(() => {
if (!user) return;
(async () => {
const [gitUser] = await request<IGitHubUser[]>(`users?since=${+(user.providerData[0].uid) - 1}&per_page=1`);
const repos = await request<IGitHubRepository[]>(`users/${gitUser.login.toLowerCase()}/repos`);

setRepositories(repos);
})();
}, [user, request]);
const { data: gitRepositories } = useQuery({
queryKey: ["github", "repositories", gitUser?.login.toLowerCase()],
queryFn: async () => githubService.getUsersRepositories(gitUser!.login),
enabled: !!gitUser
Copy link
Collaborator

@Jason2605 Jason2605 May 9, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we want to await here?
Or not mark it as async and just return the call to getUserRepository

Copy link
Member Author

@LamboCreeper LamboCreeper May 9, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need since the Promise is being directly returned. I don't think there is any advantage to having the Promise resolved within the scope of queryFn.

Discussed on Discord - will change.

});

return (
<main>
Expand All @@ -30,7 +28,7 @@ export function HomePage() {
<pre>{JSON.stringify(user)}</pre>
<h2>Repositories</h2>
<ul>
{repositories?.map(repo => <li key={repo.id}>{repo.name}</li>)}
{gitRepositories?.map((repo: IGitHubRepository) => <li key={repo.id}>{repo.name}</li>)}
</ul>
</div>
)}
Expand Down
17 changes: 0 additions & 17 deletions hosting/src/hooks/useGitHub.ts

This file was deleted.

7 changes: 6 additions & 1 deletion hosting/src/index.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
import React from "react";
import ReactDOM from "react-dom/client";
import { createBrowserRouter, RouterProvider } from "react-router-dom";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { HomePage } from "./components/pages/HomePage";
import { ErrorPage } from "./components/pages/ErrorPage";
import { ProtectedPageTemplate } from "./components/templates/ProtectedPageTemplate";
import reportWebVitals from "./reportWebVitals";
import "./index.css";

const queryClient = new QueryClient();

const router = createBrowserRouter([
{
path: "/",
Expand All @@ -27,7 +30,9 @@ const root = ReactDOM.createRoot(

root.render(
<React.StrictMode>
<RouterProvider router={router} />
<QueryClientProvider client={queryClient}>
<RouterProvider router={router} />
</QueryClientProvider>
</React.StrictMode>
);

Expand Down
24 changes: 24 additions & 0 deletions hosting/src/services/GitHubService.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { IGitHubUser } from "../interfaces/github/IGitHubUser";
import { IGitHubRepository } from "../interfaces/github/IGitHubRepository";

export class GitHubService {
private static BASE_URL = "https://api.github.com";

private async makeRequest<T>(path: string): Promise<T> {
const res = await fetch(`${GitHubService.BASE_URL}/${path}`);

return res.json();
}

async getUserById(id: number): Promise<IGitHubUser> {
const [user] = await this.makeRequest<IGitHubUser[]>(`users?since=${id - 1}&per_page=1`);

return user;
}

async getUsersRepositories(username: string): Promise<IGitHubRepository[]> {
return this.makeRequest(`users/${username.toLowerCase()}/repos`);
}
}

export const githubService = new GitHubService();
Loading