-
Notifications
You must be signed in to change notification settings - Fork 3
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
[Feat/#474] responsive basic setting & main page 임시 responsive 뷰 적용 #475
Changes from all commits
17372ad
68d89c2
710d1a9
7ab716e
b6c6227
0c55c50
dbc4859
abfc3cc
5592f53
ac55ed7
f1bae62
487730c
b79e049
4cfb9e7
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
import { Slot } from '@radix-ui/react-slot'; | ||
import { ReactNode, useContext, useEffect, useState } from 'react'; | ||
import { MOBILE_MEDIA_QUERY } from '../../../styles/mediaQuery'; | ||
import { ResponsiveContext } from './context'; | ||
interface ResponsivePropTypes { | ||
children: ReactNode; | ||
only: AvailableSize; | ||
asChild?: boolean; | ||
} | ||
|
||
type AvailableSize = 'mobile' | 'desktop'; | ||
|
||
const Responsive = ({ children, only, asChild }: ResponsivePropTypes) => { | ||
const [current, setCurrent] = useState<AvailableSize | null>(null); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. P5) current의 초기 값을 null로 설정해준 이유가 궁금해요 ! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. current는 추후 useEffect에 브라우저 API를 통해 값이 설정되므로 값이 할당되기 전에는 mobile, desktop이 아닌 null값을 가지고 있어야한다는 판단이였습니다. |
||
|
||
const Comp = asChild ? Slot : 'div'; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. p5) 굿 |
||
|
||
const { mobileOnlyClassName, desktopOnlyClassName } = useContext(ResponsiveContext); | ||
|
||
const selectedClassName = () => { | ||
if (only === 'desktop') { | ||
return desktopOnlyClassName; | ||
} else if (only === 'mobile') { | ||
return mobileOnlyClassName; | ||
} else { | ||
throw new Error(`잘못된 타입의 only값 : ${only}`); | ||
} | ||
}; | ||
|
||
useEffect(() => { | ||
const mobileMedia = window.matchMedia(MOBILE_MEDIA_QUERY); | ||
const handleCurrentChange = (e: MediaQueryListEvent) => { | ||
setCurrent(e.matches ? 'mobile' : 'desktop'); | ||
}; | ||
mobileMedia.addEventListener('change', handleCurrentChange); | ||
|
||
return () => { | ||
mobileMedia.removeEventListener('change', handleCurrentChange); | ||
}; | ||
}, []); | ||
return current === null || only === current ? ( | ||
<Comp className={`${selectedClassName()}`}>{children}</Comp> | ||
) : ( | ||
<></> | ||
Comment on lines
+41
to
+44
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. P3) 삼항연산자 대신 && 연산자를 사용해서 불필요한 코드를 최소화 할 수 있을 것 같습니다 ! 아니면 빈 태그를 리턴해주시는 이유가 있을까요 ? return current === null || only === current && (
<Comp className={`${selectedClassName()}`}>{children}</Comp>
); There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 코드가 거짓일 때 빈 fragment를 반환함으로서 명시적으로 빈 값을 나타내기 위해서 작성하였습니다. |
||
); | ||
}; | ||
|
||
export default Responsive; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
import { Global, css } from '@emotion/react'; | ||
import { ReactNode } from 'react'; | ||
import { MOBILE_MEDIA_QUERY } from '../../../styles/mediaQuery'; | ||
import { ResponsiveContext } from './context'; | ||
interface ResponsiveProviderProps { | ||
children: ReactNode; | ||
} | ||
|
||
const ResponsiveProvider = ({ children }: ResponsiveProviderProps) => { | ||
const mobileOnlyClassName = `responsive-mobile-only`; | ||
const desktopOnlyClassName = `responsive-desktop-only`; | ||
|
||
const ResponsiveClassName = css` | ||
.${mobileOnlyClassName} { | ||
display: none !important; | ||
} | ||
Comment on lines
+14
to
+16
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. P3) !important를 사용하는 대신 쌓임맥락을 고려해서 스타일 우선순위를 높여볼 수도 있을 것 같습니다. 해당 방법이 통하지 않아서 !important 사용하신 걸까요 ?? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 해당 로직은 모든 페이지에서 사용되는 부분입니다. 이것이 서드파트 라이브러리일 수도 있고 모든 부분의 쌓임맥락을 고려할 수는 없기에 !important를 사용하였습니다. |
||
.${desktopOnlyClassName} { | ||
display: block !important; | ||
} | ||
|
||
@media ${MOBILE_MEDIA_QUERY} { | ||
.${mobileOnlyClassName} { | ||
display: block !important; | ||
} | ||
.${desktopOnlyClassName} { | ||
display: none !important; | ||
} | ||
} | ||
`; | ||
return ( | ||
<ResponsiveContext.Provider value={{ mobileOnlyClassName, desktopOnlyClassName }}> | ||
<Global styles={ResponsiveClassName} /> | ||
{children} | ||
</ResponsiveContext.Provider> | ||
); | ||
}; | ||
|
||
export default ResponsiveProvider; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
import { createContext } from 'react'; | ||
|
||
interface ResponsiveContextValue { | ||
mobileOnlyClassName: string; | ||
desktopOnlyClassName: string; | ||
} | ||
|
||
export const ResponsiveContext = createContext<ResponsiveContextValue>( | ||
//ResponsiveProvider로 감싸져있지 않은 컴포넌트에서 값을 접근했을 때 또는 Context가 제대로 초기화되지 않았을 때 에러를 발생시켜 디버깅을 쉽게하기 위함 | ||
new Proxy({} as ResponsiveContextValue, { | ||
get() { | ||
throw new Error('ResponsiveProvider가 필요합니다.'); | ||
}, | ||
}), | ||
); | ||
Comment on lines
+1
to
+15
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. p5) 저희는 전체 컴포넌트들이 다 프로바이더로 감싸져있는데 이 디버깅이 필요한 경우가 있나요?? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 누군가 실수로 프로바이더 영역 외에 컴포넌트를 만들어 해당 ResponsiveContext를 사용할 경우 디버깅에 유리합니다. 해당 로직은 에러처리를 용이하기 위해 작성한 로직입니다. 휴먼에러는 언제든 발생할 수 있으니까요! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
p5) 지우기~