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

Refactor/#308: 사용자의 전공 상태 정보(useState) 삭제 #309

Merged
merged 6 commits into from
Jan 11, 2024
12 changes: 4 additions & 8 deletions src/components/Card/InformCard/index.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import MajorContext from '@contexts/major';
import useModals from '@hooks/useModals';
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import Major from '@type/major';
import { IconKind } from '@type/styles/icon';
import { act } from 'react-dom/test-utils';
import { MemoryRouter } from 'react-router-dom';
Expand Down Expand Up @@ -38,18 +37,14 @@ const INFORM_CARD: INFORM_CARD_DATA = {
};

const setMajorMock = (isRender: boolean) => {
const mockMajor: Major = isRender ? null : '컴퓨터인공지능학부';
const mockGetMajor = jest.fn();
const mockSetMajor = jest.fn();

jest.mock('react', () => ({
...jest.requireActual('react'),
useState: () => [mockMajor, mockSetMajor, graduationLink],
}));
mockGetMajor.mockReturnValue(isRender ? null : '컴퓨터인공지능학부');

return {
major: mockMajor,
getMajor: mockGetMajor,
setMajor: mockSetMajor,
graduationLink,
};
};

Expand All @@ -76,6 +71,7 @@ jest.mock('@hooks/useModals', () => {

describe('InformCard 컴포넌트 테스트', () => {
const oldWindowLocation = window.location;

beforeEach(() => {
Object.defineProperty(window, 'location', {
configurable: true,
Expand Down
17 changes: 7 additions & 10 deletions src/components/Providers/MajorProvider/index.tsx
Original file line number Diff line number Diff line change
@@ -1,22 +1,19 @@
import MajorContext from '@contexts/major';
import React, { useEffect, useState } from 'react';
import React from 'react';

import MajorStorage from './major-storage';

interface MajorProviderProps {
children: React.ReactNode;
}

const MajorProvider = ({ children }: MajorProviderProps) => {
const [major, setMajor] = useState<string | null>(null);

useEffect(() => {
const storedMajor = localStorage.getItem('major');
if (!storedMajor) return;
const MAJOR_STORAGE_KEY = 'major' as string;

setMajor(storedMajor);
}, []);
const MajorProvider = ({ children }: MajorProviderProps) => {
const majorStorage = new MajorStorage(MAJOR_STORAGE_KEY);

return (
<MajorContext.Provider value={{ major, setMajor }}>
<MajorContext.Provider value={majorStorage}>
{children}
</MajorContext.Provider>
);
Expand Down
23 changes: 23 additions & 0 deletions src/components/Providers/MajorProvider/major-storage.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
interface IMajorStorage {
getMajor: () => string | null;
setMajor: (major: string) => void;
}

class MajorStorage implements IMajorStorage {
private TOKEN_KEY;

constructor(key: string) {
this.TOKEN_KEY = key;
}

getMajor() {
const major = localStorage.getItem(this.TOKEN_KEY);
return major;
}

setMajor(major: string) {
localStorage.setItem(this.TOKEN_KEY, major);
}
}

export default MajorStorage;
3 changes: 1 addition & 2 deletions src/components/Providers/OverlayProvider/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@ import Modal from '@components/Common/Modal';
import OverlayContext from '@contexts/overlays';
import useModals from '@hooks/useModals';
import useUserLocation from '@hooks/useUserLocation';
import React, { useMemo } from 'react';
import { Outlet } from 'react-router-dom';
import React from 'react';

import CustomOverlay from './overlay';

Expand Down
4 changes: 2 additions & 2 deletions src/contexts/major.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import Major from '@type/major';
import { createContext } from 'react';

interface MajorState {
major: Major;
setMajor: React.Dispatch<React.SetStateAction<Major>>;
getMajor: () => Major;
setMajor: (major: string) => void;
}

const MajorContext = createContext<MajorState | null>(null);
Expand Down
12 changes: 9 additions & 3 deletions src/hooks/useMajor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,19 @@ import MajorContext from '@contexts/major';
import { useContext } from 'react';

const useMajor = () => {
const context = useContext(MajorContext);
const majorStorage = useContext(MajorContext);

if (!context) {
if (!majorStorage) {
throw new Error('MajorContext does not exists.');
}

return context;
const major = majorStorage.getMajor();
const setMajor = majorStorage.setMajor.bind(majorStorage);

return {
major,
setMajor,
};
};

export default useMajor;
3 changes: 2 additions & 1 deletion src/pages/MajorDecision/index.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ jest.mock('react-router-dom', () => ({
}));

describe.skip('학과선택 페이지 로직 테스트', () => {
const mockGetMajor = jest.fn();
const mockSetMajor = jest.fn();

beforeEach(() => {
Expand All @@ -33,7 +34,7 @@ describe.skip('학과선택 페이지 로직 테스트', () => {
<MemoryRouter>
<MajorContext.Provider
value={{
major: null,
getMajor: mockGetMajor,
setMajor: mockSetMajor,
}}
>
Expand Down