Skip to content

Commit

Permalink
Merge pull request #41 from capstone-maru/fix/persist-effect
Browse files Browse the repository at this point in the history
fix: 상태 관련 로직 정리
  • Loading branch information
cjeongmin authored Apr 2, 2024
2 parents adffe33 + 3ed09a7 commit 1f3312b
Show file tree
Hide file tree
Showing 9 changed files with 52 additions and 56 deletions.
2 changes: 1 addition & 1 deletion src/app/lib/providers/AuthProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export function AuthProvider({ children }: { children: React.ReactNode }) {
}

if (auth === null) {
const refreshToken = load({ type: 'local', key: 'refreshToken' });
const refreshToken = load<string>({ type: 'local', key: 'refreshToken' });
if (refreshToken !== null) {
postTokenRefresh(refreshToken)
.then(({ data }) => {
Expand Down
9 changes: 3 additions & 6 deletions src/app/pages/main-page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,10 @@
import { useQuery } from '@tanstack/react-query';
import Link from 'next/link';
import { useRouter } from 'next/navigation';
import { useEffect, useState } from 'react';
import { useEffect } from 'react';
import styled from 'styled-components';

import { UserCard } from '@/components/main-page';
import { type User } from '@/entities/user';
import { getUserData, useAuthActions, useAuthValue } from '@/features/auth';

const styles = {
Expand Down Expand Up @@ -52,20 +51,18 @@ export function MainPage() {

const auth = useAuthValue();
const { setAuthUserData } = useAuthActions();
const [user, setUserData] = useState<User | null>(null);

const { data } = useQuery({
queryKey: ['/api/auth/initial/info'],
queryFn: getUserData,
enabled: auth !== null,
enabled: auth?.refreshToken !== null,
});

useEffect(() => {
if (data !== undefined) {
const userData = data.data;

setAuthUserData(userData);
setUserData(userData);
if (userData.initialized) {
router.replace('/profile');
}
Expand All @@ -76,7 +73,7 @@ export function MainPage() {
<styles.container>
<styles.mateRecommendationsContainer>
<styles.mateRecommendationTitle>
{user?.name}님의 추천 메이트
{auth?.user?.name}님의 추천 메이트
</styles.mateRecommendationTitle>
<styles.mateRecommendation>
<Link href="/profile/memberId">
Expand Down
2 changes: 1 addition & 1 deletion src/app/pages/shared-posts.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ export function SharedPostsPage() {
const { data } = useQuery({
queryKey: ['/api/auth/initial/info'],
queryFn: getUserData,
enabled: auth !== null,
enabled: auth?.refreshToken !== null,
});

useEffect(() => {
Expand Down
36 changes: 24 additions & 12 deletions src/components/NavigationBar.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
'use client';

import { useQuery } from '@tanstack/react-query';
import Link from 'next/link';
import { useRouter } from 'next/navigation';
import styled from 'styled-components';
Expand All @@ -8,6 +9,7 @@ import { SearchBox } from './SearchBox';

import {
getAuthLogout,
getUserData,
useAuthActions,
useAuthIsLogin,
useAuthValue,
Expand Down Expand Up @@ -74,6 +76,26 @@ export function NavigationBar() {
const auth = useAuthValue();
const { logout } = useAuthActions();

const { data } = useQuery({
queryKey: ['/api/auth/initial/info'],
queryFn: getUserData,
enabled: auth?.refreshToken !== null,
});

const handleLogout = () => {
const refreshToken = load<string>({ type: 'local', key: 'refreshToken' });
if (refreshToken !== null) {
getAuthLogout(refreshToken)
.then(() => {
router.replace('/');
logout();
})
.catch(err => {
console.error(err);
});
}
};

return (
<styles.container>
<styles.utils>
Expand All @@ -85,21 +107,11 @@ export function NavigationBar() {
<styles.links>
<Link href="/shared">메이트찾기</Link>
<Link href="/community">커뮤니티</Link>
<Link href={`/profile/${auth?.user?.memberId}`}>마이페이지</Link>
<Link href={`/profile/${data?.data.memberId}`}>마이페이지</Link>
{isLogin && (
<styles.logout
onClick={() => {
const refreshToken = load({ type: 'local', key: 'refreshToken' });
if (refreshToken !== null) {
getAuthLogout(refreshToken)
.then(() => {
router.replace('/');
logout();
})
.catch(err => {
console.error(err);
});
}
handleLogout();
}}
>
로그아웃
Expand Down
9 changes: 2 additions & 7 deletions src/features/auth/auth.action.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,11 @@ export const useAuthActions = () => {
const [, setAuth] = useRecoilState(authState);

const login = useCallback(
(auth: Auth & { accessToken: string }) => {
(auth: Auth) => {
axios.defaults.headers.common.Authorization = `Bearer ${auth.accessToken}`;
save({ type: 'local', key: 'refreshToken', value: auth.refreshToken });
save({ type: 'local', key: 'expiresIn', value: `${auth.expiresIn}` });
setAuth({
expiresIn: auth.expiresIn,
refreshToken: auth.refreshToken,
user: auth.user,
});
setAuth(auth);
},
[setAuth],
);
Expand All @@ -34,7 +30,6 @@ export const useAuthActions = () => {

const setAuthUserData = useCallback(
(user: User) => {
console.log(user);
setAuth(prev => {
if (prev === null) return null;
return {
Expand Down
8 changes: 0 additions & 8 deletions src/features/auth/auth.atom.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,7 @@ import { atom } from 'recoil';

import { type Auth } from './auth.model';

import { storageEffect } from '@/shared/persist';

export const authState = atom<Auth | null>({
key: 'authState',
default: null,
effects: [
storageEffect({
key: 'auth-state',
storageType: 'session',
}),
],
});
1 change: 1 addition & 0 deletions src/features/auth/auth.model.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { type User } from '@/entities/user';

export interface Auth {
accessToken: string;
refreshToken: string;
expiresIn: number;
user?: User;
Expand Down
11 changes: 7 additions & 4 deletions src/shared/persist/effect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,19 @@ export const storageEffect =
({ setSelf, onSet }) => {
if (typeof window === 'undefined') return;

const savedValue = load({ type: storageType, key });
if (savedValue != null) {
setSelf(load({ type: storageType, key }) as StoredType);
const savedValue = load<StoredType>({
type: storageType,
key,
});
if (savedValue !== null) {
setSelf(savedValue);
}

onSet((newValue: StoredType | DefaultValue, _, isReset: boolean) => {
if (isReset) {
remove({ type: storageType, key });
} else {
save({ type: storageType, key, value: JSON.stringify(newValue) });
save({ type: storageType, key, value: newValue });
}
});
};
30 changes: 13 additions & 17 deletions src/shared/storage/storage.ts
Original file line number Diff line number Diff line change
@@ -1,38 +1,34 @@
export type StorageType = 'session' | 'local';

export const save = ({
export const save = <T>({
type,
key,
value,
}: {
type: StorageType;
key: string;
value: string;
value: T;
}) => {
if (typeof window === 'undefined') return;

if (type === 'local') {
localStorage.setItem(key, value);
} else {
sessionStorage.setItem(key, value);
}
const storage = type === 'local' ? localStorage : sessionStorage;
storage.setItem(key, JSON.stringify(value));
};

export const load = ({ type, key }: { type: StorageType; key: string }) => {
export const load = <T>({ type, key }: { type: StorageType; key: string }) => {
if (typeof window === 'undefined') return null;

if (type === 'local') {
return localStorage.getItem(key);
}
return sessionStorage.getItem(key);
const storage = type === 'local' ? localStorage : sessionStorage;
const storedValue = storage.getItem(key);
if (storedValue === null) return null;

const parsedValue = JSON.parse(storedValue) as T;
return parsedValue;
};

export const remove = ({ type, key }: { type: StorageType; key: string }) => {
if (typeof window === 'undefined') return;

if (type === 'local') {
localStorage.removeItem(key);
} else {
sessionStorage.removeItem(key);
}
const storage = type === 'local' ? localStorage : sessionStorage;
storage.removeItem(key);
};

0 comments on commit 1f3312b

Please sign in to comment.