Skip to content
This repository has been archived by the owner on Dec 11, 2024. It is now read-only.

Commit

Permalink
refactor: fetchをProvider内でやっちゃう、fetchUserでどこからでもupdateできるようにする
Browse files Browse the repository at this point in the history
  • Loading branch information
sor4chi committed Dec 29, 2023
1 parent f749eea commit 48f9ed5
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 45 deletions.
45 changes: 13 additions & 32 deletions client/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,41 +1,22 @@
import { BrowserRouter } from "react-router-dom";
import { LoadingOverlay } from "./components/loading-overlay/loading-overlay";
import { AppRoutes } from "./routes";
import { Suspense, useCallback, useEffect } from "react";
import { useAuth } from "./providers/auth";
import { object, string, safeParse } from "valibot";

const UserMeResponseSchema = object({
name: string(),
image_url: string(),
});
import { Suspense } from "react";
import { LoadingOverlayProvider } from "./providers/loading-overlay.tsx";
import { AuthProvider } from "./providers/auth.tsx";

function App() {
const { setUser } = useAuth();
const initializeUser = useCallback(async () => {
const res = await fetch("/api/users/me");
if (!res.ok) throw new Error("Unauthorized");
const user = safeParse(UserMeResponseSchema, await res.json());
if (!user.success) throw new Error("Invalid response");
setUser({
name: user.output.name,
imageURL: user.output.image_url,
});
}, [setUser]);

useEffect(() => {
void initializeUser();
}, [initializeUser]);

return (
<>
<LoadingOverlay />
<BrowserRouter>
<Suspense>
<AppRoutes />
</Suspense>
</BrowserRouter>
</>
<AuthProvider>
<LoadingOverlayProvider>
<LoadingOverlay />
<BrowserRouter>
<Suspense>
<AppRoutes />
</Suspense>
</BrowserRouter>
</LoadingOverlayProvider>
</AuthProvider>
);
}

Expand Down
8 changes: 1 addition & 7 deletions client/src/main.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,11 @@
import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App.tsx";
import { LoadingOverlayProvider } from "./providers/loading-overlay.tsx";
import { AuthProvider } from "./providers/auth.tsx";

import "@/styles/global.css";

ReactDOM.createRoot(document.getElementById("root")!).render(
<React.StrictMode>
<AuthProvider>
<LoadingOverlayProvider>
<App />
</LoadingOverlayProvider>
</AuthProvider>
<App />
</React.StrictMode>
);
33 changes: 27 additions & 6 deletions client/src/providers/auth.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
import React, { createContext, useState } from "react";
import React, { createContext, useCallback, useEffect, useState } from "react";
import { object, string, safeParse, number } from "valibot";

const UserModel = object({
id: number(),
name: string(),
image_url: string(),
});

interface User {
name: string;
Expand All @@ -8,13 +15,14 @@ interface User {
interface AuthContextProps {
user: User | null;
isAuthenticated: boolean;
setUser: (user: User) => void;
fetchUser: () => Promise<void>;
}

const AuthContext = createContext<AuthContextProps>({
user: null,
isAuthenticated: false,
setUser: () => {},
// eslint-disable-next-line @typescript-eslint/no-empty-function
fetchUser: async () => {},
});

interface AuthProviderProps {
Expand All @@ -24,13 +32,26 @@ interface AuthProviderProps {
export const AuthProvider = ({ children }: AuthProviderProps) => {
const [user, setUser] = useState<User | null>(null);

const fetchUser = useCallback(async () => {
const res = await fetch("/api/user/me");
if (!res.ok) throw new Error("Unauthorized");
const user = safeParse(UserModel, await res.json());
if (!user.success) throw new Error("Invalid response");
setUser({
name: user.output.name,
imageURL: user.output.image_url,
});
}, [setUser]);

useEffect(() => {
void fetchUser();
}, [fetchUser]);

return (
<AuthContext.Provider value={{ user, isAuthenticated: !!user, setUser }}>
<AuthContext.Provider value={{ user, isAuthenticated: !!user, fetchUser }}>
{children}
</AuthContext.Provider>
);
};

export const useAuth = () => React.useContext(AuthContext);


0 comments on commit 48f9ed5

Please sign in to comment.