Skip to content

Commit

Permalink
[Fix] deviceType undefined 에러 뜨는 이슈 해결 (#411)
Browse files Browse the repository at this point in the history
* feat: device type context 생성

* refactor: form context에서 device type 제거

* feat: device type context provider 감싸주기

* refactor: 기존 Form context의 deviceType을 DeviceType context의 deviceType으로 대체

* refactor: device type context 적용
  • Loading branch information
eonseok-jeon authored Aug 17, 2024
1 parent dbd0713 commit 0dbd2e6
Show file tree
Hide file tree
Showing 51 changed files with 170 additions and 134 deletions.
22 changes: 14 additions & 8 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import { HelmetProvider } from 'react-helmet-async';
import { RouterProvider, createBrowserRouter } from 'react-router-dom';

import Layout from '@components/Layout';
import { useDevice } from '@hooks/useDevice';
import { DeviceTypeContext } from '@store/deviceTypeContext';
import { RecruitingInfoContext, RecruitingInfoType } from '@store/recruitingInfoContext';
import { ModeType, ThemeContext } from '@store/themeContext';
import { dark, light } from 'styles/theme.css';
Expand Down Expand Up @@ -109,6 +111,8 @@ const App = () => {
}, []),
};

const deviceType = useDevice();

useEffect(() => {
if (!isAmplitudeInitialized) {
init(import.meta.env.VITE_AMPLITUDE_API_KEY);
Expand All @@ -129,14 +133,16 @@ const App = () => {
<SessionExpiredDialog ref={sessionRef} />
<HelmetProvider>
<ThemeContext.Provider value={themeContextValue}>
<RecruitingInfoContext.Provider value={recruitingInfoContextValue}>
<QueryClientProvider client={queryClient}>
<ReactQueryDevtools />
<div className={isLight ? light : dark}>
<RouterProvider router={router} />
</div>
</QueryClientProvider>
</RecruitingInfoContext.Provider>
<DeviceTypeContext.Provider value={{ deviceType }}>
<RecruitingInfoContext.Provider value={recruitingInfoContextValue}>
<QueryClientProvider client={queryClient}>
<ReactQueryDevtools />
<div className={isLight ? light : dark}>
<RouterProvider router={router} />
</div>
</QueryClientProvider>
</RecruitingInfoContext.Provider>
</DeviceTypeContext.Provider>
</ThemeContext.Provider>
</HelmetProvider>
</>
Expand Down
6 changes: 3 additions & 3 deletions src/common/components/Button/index.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { useId, type ButtonHTMLAttributes, type ReactNode } from 'react';
import { useContext, useId, type ButtonHTMLAttributes, type ReactNode } from 'react';
import { Link, To } from 'react-router-dom';

import { useDevice } from '@hooks/useDevice';
import { DeviceTypeContext } from '@store/deviceTypeContext';
import ButtonLoading from 'views/loadings/ButtonLoading';

import { buttonFontVar, container, outsideBox, paddings } from './style.css';
Expand All @@ -26,7 +26,7 @@ const Button = ({
isLink = false,
...buttonElementProps
}: ButtonProps) => {
const deviceType = useDevice();
const { deviceType } = useContext(DeviceTypeContext);
const { disabled, type = 'button' } = buttonElementProps;
const Tag = isLink ? Link : 'button';

Expand Down
7 changes: 3 additions & 4 deletions src/common/components/Callout/index.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,19 @@
import { colors } from '@sopt-makers/colors';
import { IconAlertCircle } from '@sopt-makers/icons';
import { useContext, type HTMLAttributes, type ReactNode } from 'react';

import { useDevice } from '@hooks/useDevice';
import { DeviceTypeContext } from '@store/deviceTypeContext';

import { buttonVar, container, warningWrapperVar } from './style.css';

import type { HTMLAttributes, ReactNode } from 'react';

interface CalloutProps extends HTMLAttributes<HTMLElement> {
children?: ReactNode;
size?: 'sm' | 'lg';
Button?: ReactNode;
}

const Callout = ({ children, size = 'sm', Button, ...calloutElementProps }: CalloutProps) => {
const deviceType = useDevice();
const { deviceType } = useContext(DeviceTypeContext);
return (
<article className={container[deviceType === 'DESK' ? size : deviceType]} {...calloutElementProps}>
<div className={warningWrapperVar[deviceType]}>
Expand Down
6 changes: 3 additions & 3 deletions src/common/components/Dialog/index.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { forwardRef, type DialogHTMLAttributes, type ReactNode } from 'react';
import { forwardRef, useContext, type DialogHTMLAttributes, type ReactNode } from 'react';
import { createPortal } from 'react-dom';

import { useDevice } from '@hooks/useDevice';
import { DeviceTypeContext } from '@store/deviceTypeContext';

import { containerVar } from './style.css';

Expand All @@ -10,7 +10,7 @@ interface DialogProps extends DialogHTMLAttributes<HTMLDialogElement> {
}

const Dialog = forwardRef<HTMLDialogElement, DialogProps>(({ children, ...dialogElementProps }: DialogProps, ref) => {
const deviceType = useDevice();
const { deviceType } = useContext(DeviceTypeContext);

return createPortal(
<dialog ref={ref} className={containerVar[deviceType]} {...dialogElementProps}>
Expand Down
4 changes: 2 additions & 2 deletions src/common/components/Input/components/Description/index.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { useContext } from 'react';

import { TextBoxProps } from '@components/Input/types';
import { DeviceTypeContext } from '@store/deviceTypeContext';

import { descriptionFontVar, descriptionVar } from './style.css';
import { FormContext } from '../TextBox';

// TextBox 내부 Input 하단의 부가텍스트
const Description = ({ children, styleType = 'default' }: Pick<TextBoxProps, 'children' | 'styleType'>) => {
const { deviceType } = useContext(FormContext);
const { deviceType } = useContext(DeviceTypeContext);

return <div className={`${descriptionVar[styleType]} ${descriptionFontVar[deviceType]}`}>{children}</div>;
};
Expand Down
4 changes: 2 additions & 2 deletions src/common/components/Input/components/InputButton/index.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import { useContext } from 'react';

import Button from '@components/Button';
import { DeviceTypeContext } from '@store/deviceTypeContext';

import { buttonVar } from './style.css';
import { InputButtonProps } from './types';
import { FormContext } from '../TextBox';

// TextBox 내부 InputLine 우측 버튼
const InputButton = ({ isLoading, text, ...props }: InputButtonProps) => {
const { deviceType } = useContext(FormContext);
const { deviceType } = useContext(DeviceTypeContext);
return (
<Button isLoading={isLoading} className={buttonVar[deviceType]} {...props}>
{text}
Expand Down
5 changes: 4 additions & 1 deletion src/common/components/Input/components/InputLine/index.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { ChangeEvent, useContext } from 'react';
import { useFormContext } from 'react-hook-form';

import { DeviceTypeContext } from '@store/deviceTypeContext';

import { inputFontVar, inputLineVar, inputVar } from './style.css';
import { formatBirthdate } from './utils/formatBirthdate';
import { formatPhoneNumber } from './utils/formatPhoneNumber';
Expand All @@ -24,7 +26,8 @@ const InputLine = ({
trigger,
setValue,
} = useFormContext();
const { required, deviceType } = useContext(FormContext);
const { required } = useContext(FormContext);
const { deviceType } = useContext(DeviceTypeContext);
const { maxLength, minLength } = inputElementProps;
const { defaultValue } = inputElementProps;

Expand Down
6 changes: 3 additions & 3 deletions src/common/components/Input/components/InputTheme/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ import useMutateCheckUser from '@components/Input/hooks/useMutateCheckUser';
import useMutateSendCode from '@components/Input/hooks/useMutateSendCode';
import { VALIDATION_CHECK } from '@constants/validationCheck';
import useScrollToHash from '@hooks/useScrollToHash';
import { DeviceTypeContext } from '@store/deviceTypeContext';

import { successVar } from './style.css';
import InputLine from '../InputLine';
import { FormContext } from '../TextBox';

export const TextBox이름 = () => {
return (
Expand Down Expand Up @@ -40,7 +40,7 @@ export const TextBox이메일 = ({
isVerified,
onChangeVerification,
}: TextBox이메일Props) => {
const { deviceType } = useContext(FormContext);
const { deviceType } = useContext(DeviceTypeContext);
const location = useLocation();
const navigate = useNavigate();

Expand Down Expand Up @@ -188,7 +188,7 @@ export const TextBox이메일 = ({
};

export const TextBox비밀번호 = () => {
const { deviceType } = useContext(FormContext);
const { deviceType } = useContext(DeviceTypeContext);

const location = useLocation();
const textVar = location.pathname === '/password' ? '새 비밀번호' : '비밀번호';
Expand Down
10 changes: 5 additions & 5 deletions src/common/components/Input/components/TextBox/index.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { createContext } from 'react';
import { createContext, useContext } from 'react';

import { TextBoxProps } from '@components/Input/types';
import { DeviceType, useDevice } from '@hooks/useDevice';
import { DeviceTypeContext } from '@store/deviceTypeContext';

import { circle, containerVar, titleVar } from './style.css';

export const FormContext = createContext({} as Pick<TextBoxProps, 'required'> & { deviceType: DeviceType });
export const FormContext = createContext({} as Pick<TextBoxProps, 'required'>);

// TextBox Container
export const TextBox = ({
Expand All @@ -15,10 +15,10 @@ export const TextBox = ({
size = 'md',
required,
}: Pick<TextBoxProps, 'children' | 'label' | 'name' | 'size' | 'required'>) => {
const deviceType = useDevice();
const { deviceType } = useContext(DeviceTypeContext);

return (
<FormContext.Provider value={{ required, deviceType }}>
<FormContext.Provider value={{ required }}>
<div className={containerVar[deviceType === 'DESK' ? size : deviceType]}>
<label className={titleVar[deviceType]} htmlFor={name}>
<span>{label}</span>
Expand Down
5 changes: 3 additions & 2 deletions src/common/components/Input/components/Timer/index.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
import { differenceInSeconds } from 'date-fns';
import { useContext, useEffect, useState } from 'react';

import { DeviceTypeContext } from '@store/deviceTypeContext';

import { timerVar } from './style.css';
import { TimerProps } from './types';
import formatTimer from './utils/formatTimer';
import { FormContext } from '../TextBox';

const INITIAL_TIME = 300;

// TextBox 내부 타이머
const Timer = ({ isActive, onResetTimer }: TimerProps) => {
const { deviceType } = useContext(FormContext);
const { deviceType } = useContext(DeviceTypeContext);
const [seconds, setSeconds] = useState(INITIAL_TIME - 1);

useEffect(() => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { track } from '@amplitude/analytics-browser';
import { useContext } from 'react';
import { NavLink } from 'react-router-dom';

import { useDevice } from '@hooks/useDevice';
import { DeviceTypeContext } from '@store/deviceTypeContext';

import { menuItemVar, menuLinkVar } from './style.css';

Expand All @@ -15,7 +16,7 @@ interface MenuItemProps {
}

const MenuItem = ({ text, path, target, amplitudeId, className, onClick }: MenuItemProps) => {
const deviceType = useDevice();
const { deviceType } = useContext(DeviceTypeContext);

return (
<li className={`${className} ${menuItemVar[deviceType]}`}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@ import { reset, track } from '@amplitude/analytics-browser';
import { useContext, useEffect, useState } from 'react';
import { useLocation, useNavigate } from 'react-router-dom';

import { useDevice } from '@hooks/useDevice';
import { DeviceTypeContext } from '@store/deviceTypeContext';
import { RecruitingInfoContext } from '@store/recruitingInfoContext';

import { dimmedBgVar, menuContainerVar, menuList, menuMobListVar } from './style.css';
import { MENU_ITEMS, MENU_ITEMS_MAKERS } from '../../contants';
import MenuItem from '../MenuItem';

const MenuList = ({ isMenuOpen, onClickMenuToggle }: { isMenuOpen?: boolean; onClickMenuToggle?: () => void }) => {
const deviceType = useDevice();
const { deviceType } = useContext(DeviceTypeContext);
const navigate = useNavigate();
const { pathname } = useLocation();
const [isShown, setIsShown] = useState(isMenuOpen);
Expand Down
4 changes: 2 additions & 2 deletions src/common/components/Layout/components/Header/Nav/index.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import { IconMenu, IconXClose } from '@sopt-makers/icons';
import { useContext } from 'react';

import { useDevice } from '@hooks/useDevice';
import { DeviceTypeContext } from '@store/deviceTypeContext';
import { ThemeContext } from '@store/themeContext';
import { theme } from 'styles/theme.css';

import MenuList from './MenuList';
import { menuIconVar } from './style.css';

const Nav = ({ isMenuOpen, onClickMenuToggle }: { isMenuOpen: boolean; onClickMenuToggle: () => void }) => {
const deviceType = useDevice();
const { deviceType } = useContext(DeviceTypeContext);
const { isLight } = useContext(ThemeContext);

return deviceType !== 'DESK' ? (
Expand Down
4 changes: 2 additions & 2 deletions src/common/components/Layout/components/Header/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { useLocation, useNavigate } from 'react-router-dom';
import MakersDarkLogo from '@assets/MakersDarkLogo';
import MakersLogo from '@assets/MakersLogo';
import NowsoptLogo from '@assets/NowsoptLogo';
import { useDevice } from '@hooks/useDevice';
import { DeviceTypeContext } from '@store/deviceTypeContext';
import { RecruitingInfoContext } from '@store/recruitingInfoContext';
import { ThemeContext } from '@store/themeContext';

Expand All @@ -13,7 +13,7 @@ import MenuList from './Nav/MenuList';
import { containerSizeVer, containerVar, logoVar } from './style.css';

const Header = () => {
const deviceType = useDevice();
const { deviceType } = useContext(DeviceTypeContext);
const [isMenuOpen, setIsMenuOpen] = useState(false);
const handleClickMenuToggle = () => {
setIsMenuOpen((prev) => !prev);
Expand Down
6 changes: 3 additions & 3 deletions src/common/components/Select/index.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { IconChevronDown } from '@sopt-makers/icons';
import { ChangeEvent } from 'react';
import { ChangeEvent, useContext } from 'react';
import { useFormContext } from 'react-hook-form';

import { circle, containerVar, titleVar } from '@components/Input/components/TextBox/style.css';
import { useDevice } from '@hooks/useDevice';
import { DeviceTypeContext } from '@store/deviceTypeContext';

import {
errorVar,
Expand All @@ -17,7 +17,7 @@ import {
import { SelectBoxProps } from './type';

const SelectBox = ({ label, name, options, size = 'sm', required, ...inputElementProps }: SelectBoxProps) => {
const deviceType = useDevice();
const { deviceType } = useContext(DeviceTypeContext);

const { register, formState, clearErrors, getValues, setValue, setError } = useFormContext();
const { errors } = formState;
Expand Down
6 changes: 3 additions & 3 deletions src/common/components/Textarea/components/Input/index.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { useEffect, type TextareaHTMLAttributes } from 'react';
import { useContext, useEffect, type TextareaHTMLAttributes } from 'react';
import { type FieldValues, type Path, useFormContext } from 'react-hook-form';

import { useDevice } from '@hooks/useDevice';
import { DeviceTypeContext } from '@store/deviceTypeContext';

import {
containerVar,
Expand All @@ -26,7 +26,7 @@ const Input = <T extends FieldValues>({
isFileInput,
...textareaElements
}: InputProps<T>) => {
const deviceType = useDevice();
const { deviceType } = useContext(DeviceTypeContext);

const {
watch,
Expand Down
6 changes: 3 additions & 3 deletions src/common/components/Textarea/components/Label/index.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Fragment, type HTMLAttributes } from 'react';
import { Fragment, useContext, type HTMLAttributes } from 'react';

import { useDevice } from '@hooks/useDevice';
import { DeviceTypeContext } from '@store/deviceTypeContext';

import { requireDot, labelStyleVar } from './style.css';

Expand All @@ -12,7 +12,7 @@ interface LabelProps extends HTMLAttributes<HTMLHeadingElement> {
}

const Label = ({ children, maxCount, required, label, ...headerElementProps }: LabelProps) => {
const deviceType = useDevice();
const { deviceType } = useContext(DeviceTypeContext);
const questionArray = children.split('\n');
const firstEmptyIndex = questionArray.indexOf('');

Expand Down
6 changes: 3 additions & 3 deletions src/common/components/Title/index.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import { ReactNode } from 'react';
import { ReactNode, useContext } from 'react';

import { useDevice } from '@hooks/useDevice';
import { DeviceTypeContext } from '@store/deviceTypeContext';

import { headingVar } from './style.css';

interface TitleProps {
children: ReactNode;
}
const Title = ({ children }: TitleProps) => {
const deviceType = useDevice();
const { deviceType } = useContext(DeviceTypeContext);
return <h1 className={headingVar[deviceType]}>{children}</h1>;
};

Expand Down
9 changes: 9 additions & 0 deletions src/common/store/deviceTypeContext.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { createContext } from 'react';

export interface DeviceTypeContextType {
deviceType: 'DESK' | 'TAB' | 'MOB';
}

export const DeviceTypeContext = createContext<DeviceTypeContextType>({
deviceType: 'DESK',
});
Loading

0 comments on commit 0dbd2e6

Please sign in to comment.