Skip to content

Commit

Permalink
Refactor: context를 사용하여 유저데이터 관리하기
Browse files Browse the repository at this point in the history
  • Loading branch information
ayoung-iya committed May 18, 2024
1 parent d607cf6 commit 9398480
Show file tree
Hide file tree
Showing 8 changed files with 111 additions and 30 deletions.
18 changes: 18 additions & 0 deletions api/auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,3 +49,21 @@ export const postSignUp = async ({ email, password }: { email: string; password:

return token;
};

export const getUser = async () => {
const token = window.localStorage.getItem('accessToken');

const response = await fetch(`${BASE_URL}/users`, {
headers: {
Authorization: `Bearer ${token}`,
},
});

const body = await response.json();

if (!response?.ok) {
throw new Error(body.message);
}

return {...body[0], imageSource: body[0]['image_source']};
};
21 changes: 3 additions & 18 deletions components/layout/header/Header.tsx
Original file line number Diff line number Diff line change
@@ -1,30 +1,15 @@
import Link from 'next/link';
import styles from './Header.module.css';
import { useEffect, useState } from 'react';
import { useContext } from 'react';
import { useRouter } from 'next/router';
import type { User } from '@/types/types';
import { getUser } from '@/api/api';
import Image from 'next/image';
import { authContext } from '@/context/authProvider';

function Header() {
const [user, setUser] = useState<User | null>(null);
const { user } = useContext(authContext);
const { pathname } = useRouter();
const headerPosition = pathname === '/folder' ? styles.static : '';

useEffect(() => {
const fetchUser = async () => {
try {
const user = await getUser();
setUser(user);
} catch (err) {
const error = err as Error;
console.error(error.message);
}
};

fetchUser();
}, []);

return (
<header className={`${styles.headerArea} ${headerPosition}`}>
<div className={styles.headerGroup}>
Expand Down
61 changes: 61 additions & 0 deletions context/authProvider.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import { getUser, postSignIn, postSignUp } from '@/api/auth';
import { PropsWithChildren, createContext, useEffect, useState } from 'react';

interface User {
id: number;
name: string;
imageSource: string;
email: string;
}

interface AuthContext {
user?: User;
signIn: (data: any) => void;
signUp: (data: any) => void;
signOut: () => void;
}

export const authContext = createContext<AuthContext>({
user: undefined,
signIn: () => {},
signUp: () => {},
signOut: () => {},
});

const AuthProvider = ({ children }: PropsWithChildren) => {
const [user, setUser] = useState<User>();

const signIn = async (data: any) => {
const { accessToken, refreshToken } = await postSignIn(data);

window.localStorage.setItem('accessToken', accessToken);
window.localStorage.setItem('refreshToken', refreshToken);
};
const signUp = async (data: any) => {
const { accessToken, refreshToken } = await postSignUp(data);

window.localStorage.setItem('accessToken', accessToken);
window.localStorage.setItem('refreshToken', refreshToken);
};

const signOut = () => {
// TODO: 로그아웃 기능 구현
};

useEffect(() => {
const fetchUser = async () => {
try {
const user = await getUser();
setUser(user);
} catch (error) {
console.error((error as Error).message);
}
};

fetchUser();
}, []);

return <authContext.Provider value={{ user, signIn, signUp, signOut }}>{children}</authContext.Provider>;
};

export default AuthProvider;
11 changes: 11 additions & 0 deletions hooks/useAuth.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { authContext } from '@/context/authProvider';
import { useContext } from 'react';

export const useAuth = () => {
const context = useContext(authContext);
if (!context) {
throw new Error('반드시 AuthProvider 안에서 사용해야 합니다.');
}

return context;
};
6 changes: 6 additions & 0 deletions next.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,12 @@ const nextConfig = {
port: '',
pathname: '/badges/**',
},
{
protocol: 'https',
hostname: 'avatars.githubusercontent.com',
port: '',
pathname: '/u/**',
},
],
},
};
Expand Down
9 changes: 6 additions & 3 deletions pages/_app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import '@/styles/globals.css';
import { Noto_Sans_KR } from 'next/font/google';
import type { AppProps } from 'next/app';
import Layout from '@/components/layout/Layout';
import AuthProvider from '@/context/authProvider';

const notoSansKR = Noto_Sans_KR({
subsets: ['latin'],
Expand All @@ -11,9 +12,11 @@ const notoSansKR = Noto_Sans_KR({
export default function App({ Component, pageProps }: AppProps) {
return (
<main className={notoSansKR.className}>
<Layout>
<Component {...pageProps} />
</Layout>
<AuthProvider>
<Layout>
<Component {...pageProps} />
</Layout>
</AuthProvider>
</main>
);
}
8 changes: 3 additions & 5 deletions pages/signin.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { postSignIn } from '@/api/auth';
import InputGroup from '@/components/pages/sign/InputGroup';
import { ERROR_MESSAGE, INPUT_INFO } from '@/constants/sign';
import { useAuth } from '@/hooks/useAuth';
import styles from '@/styles/sign.module.css';
import Image from 'next/image';
import Link from 'next/link';
Expand All @@ -10,14 +11,11 @@ import { FormProvider, useForm } from 'react-hook-form';
export default function SignIn() {
const methods = useForm();
const router = useRouter();
const { signIn } = useAuth();

const onSubmit = async (data: any) => {
try {
const { accessToken, refreshToken } = await postSignIn(data);

window.localStorage.setItem('accessToken', accessToken);
window.localStorage.setItem('refreshToken', refreshToken);

signIn(data);
router.push('/folder');
} catch {
methods.setError(INPUT_INFO.email.id, {
Expand Down
7 changes: 3 additions & 4 deletions pages/signup.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { postCheckEmail, postSignUp } from '@/api/auth';
import InputGroup from '@/components/pages/sign/InputGroup';
import { INPUT_INFO } from '@/constants/sign';
import { useAuth } from '@/hooks/useAuth';
import styles from '@/styles/sign.module.css';
import Image from 'next/image';
import Link from 'next/link';
Expand All @@ -9,6 +10,7 @@ import { useState } from 'react';
import { FormProvider, useForm } from 'react-hook-form';

export default function SignIn() {
const { signUp } = useAuth();
const methods = useForm();
const [emailCheckFailed, setEmailCheckFailed] = useState(false);
const router = useRouter();
Expand All @@ -33,10 +35,7 @@ export default function SignIn() {
}

try {
const { accessToken, refreshToken } = await postSignUp({ email, password });

window.localStorage.setItem('accessToken', accessToken);
window.localStorage.setItem('refreshToken', refreshToken);
signUp({ email, password });

router.push('/folder');
} catch (error) {
Expand Down

0 comments on commit 9398480

Please sign in to comment.