github_star_9 육지수 과제 제출합니다. - #7
Conversation
for using async/await.
view focus on only presentation logic.
- page layer 추가 - globalStyle을 App.tsx로 이동(의미상 자연스럽게 느껴져서)
| &:hover { | ||
| background-color: #dcdcdc; | ||
| } | ||
| `; |
There was a problem hiding this comment.
질문이 한가지 있습니다!
css 작성하신 것 보면 한 줄이 띄워져있는 것도 있고 붙어 있는 줄도 있는 것 같은데, 이런 형태는 처음 봐서 신기해서용!
혹시 어떤 기준으로 줄을 나누신건지 알 수 있을까요?
There was a problem hiding this comment.
매번 css를 작성할 때 마다 달라지긴하는데 제가 알아보기 쉬우려고 그룹을 나눠서 개행을 해요!
예를 들어서 display: flex 관련된 그룹, padding/margin 관련된 그룹, width/height 이런식으로 나눠서 작성하면 보기에 편하더라구요!
혼자서 할 때는 잘 지키지는 않지만...
https://moo-you.tistory.com/21
옛날에 봤던 css 선언 순서와 관련된 글인데 이 글을 보면서 시작?된 것 같아요.
There was a problem hiding this comment.
오 👍
지수님 요 순서 다 외우셨나요?? ㅋㅋㅋㅋ
회사에서 맨날 놓쳐서 푸시전에 솔팅 툴 돌리는 1인..
There was a problem hiding this comment.
아녀 못 외우고 저만의 규칙? 으로 매번 달라져여ㅋㅋㅋㅋㅋㅋㅋㅋㅋ
| .background { | ||
| position: absolute; | ||
|
|
||
| z-index: -1; | ||
| top: 0; | ||
| left: 0; | ||
|
|
||
| background-color: #fcffbe; | ||
| width: 100%; | ||
| height: 100%; | ||
|
|
||
| transform: skew(-20deg); | ||
|
|
||
| animation-name: changeColor; | ||
| animation-duration: 15s; | ||
| animation-iteration-count: infinite; | ||
| } |
There was a problem hiding this comment.
styled-components에 이렇게 클래스를 선언할 수 있는지 몰랐네요.. 덕분에 좋은거 하나 알게된거 같아요 감사합니다!
| title: string; | ||
| } | ||
|
|
||
| const BeautifulTitle: React.FC<BeautifulTitle> = ({ title }) => { |
There was a problem hiding this comment.
앜ㅋㅋㅋㅋ 희라님ㅋㅋㅋ 핵웃곀ㅋㅋ
근데 저 섬세함에 감탄하고 갑니다.
| }; | ||
|
|
||
| const handleInputKeyEvent = (e: React.KeyboardEvent<HTMLInputElement>) => { | ||
| if (e.keyCode !== 13) return; |
There was a problem hiding this comment.
| if (e.keyCode !== 13) return; | |
| const ENTER = 'Enter' | |
| if (e.key !== ENTER) return; |
어떠나유 ㅎㅎ
There was a problem hiding this comment.
@lallaheeee 저 저번에 이렇게 써본거같은데 이럴 경우에 모바일 키보드에서 전송(?) 버튼 누르면 Enter만으로는 작동 안하는걸로 알아요!
There was a problem hiding this comment.
@mango906 오 새로운 사실 알아갑니다 ㅎㅎ
그렇다면 어떠나유
| if (e.keyCode !== 13) return; | |
| const ENTER = 'Enter' | |
| if (e.keyCode !== 13 || e.key !== ENTER ) return; |
There was a problem hiding this comment.
@lallaheeee e.key !== ENTER를 추가한데 특별한 이유가 있으신가요??
There was a problem hiding this comment.
@mango906
13이라는 숫자가 enter라는 걸 알기 힘드니까
상수로 값의 의미를 명확히 기술하여 가독성을 높이면 좋겠다는 생각이 들었어요 ㅎㅎ
const ENTER = 13
if( e.keyCode !== ENTER )
이ㅇㅓ도 좋을것같아여 ㅎㅎ
There was a problem hiding this comment.
찾아보니 경빈님이 말씀하신 모바일 키패드 문제도 그렇구 브라우저나 모바일 별로 key code에 대한 이슈가 있는 것 같았어요.
몇몇 사람들은 key code 처리에 대한 polyfill 함수를 만들어서 사용하는 것 같아서 그런 함수를 만드는것도 좋은 것 같아요!
There was a problem hiding this comment.
오 이런 디테일 매우 좋아요 ㅋㅋㅋㅋ
Enter가 있다는 것은 처음알았네요 👍
| <li key={name}> | ||
| <Styled.RepositoryItem href={link}> | ||
| <span className="repository-name">{name}</span> | ||
| {description && <span className="repository-description">{description}</span>} |
There was a problem hiding this comment.
레포 description도 보여주는 건가요? 섬세하시네유..👍🏻
| return <UserInfoContext.Provider value={{ userInfo, searchUsefInfo }}>{children}</UserInfoContext.Provider>; | ||
| }; | ||
|
|
||
| export default UserInfoProvider; |
There was a problem hiding this comment.
| export default UserInfoProvider; | |
| export default function useUserInfo { | |
| return useContext(UserInfoContext); | |
| } |
굉장히 사소한건데, 이렇게 사용하면 편하더라고요 ~
|
|
||
| const historyPushForSearchUserInfo = useCallback( | ||
| (username: string) => { | ||
| history.push(`?username=${username}`); |
There was a problem hiding this comment.
검색 기록을 히스토리로 관리해주는 거 좋네요 배워갑니다ㅎㅎ
| async (username: string) => { | ||
| chagePageStatus(PageStatus.Loading); | ||
|
|
||
| checkHasBeenSearched(); |
There was a problem hiding this comment.
API 요청을 중복 요청을 방지를 위해 확인하는 것 같은 네이밍처럼 느껴지는데 checkScrolled 는 어때유??
There was a problem hiding this comment.
첫 검색 시에 moveTop state를 true로 변경시켜주고
moveTop state가 false에서 true로 변경되면 타이틀이 상단으로 움직이는 animation이 실행되요.
moveTop state를 보고 변경해주는 함수가 checkHasBeenSearched이고
첫 검색이후에는 아무런 작업을 하지 않습니다.
희라님이 API 요청을 중복 요청을 방지를 위해 확인하는 함수라고 생각하셨으니 저 함수의 네이밍이 잘못된 것 같네요!
좀 더 괜찮은 이름을 생각해보는게 좋겠어요!
| const request = <T>(path: string, option: Option) => { | ||
| return fetch(`${GITHUB_API_BASE_URL}${path}`, option).then((res) => res.json() as Promise<T>); | ||
| }; | ||
|
|
There was a problem hiding this comment.
분리 하신 걸를 보니 다른 프로젝트에서도 재사용하실 것 같은데
apiPaths 처럼 baseURL을 분리해도 좋을 것 같아유 ㅎㅎ
| const request = <T>(path: string, option: Option) => { | |
| return fetch(`${GITHUB_API_BASE_URL}${path}`, option).then((res) => res.json() as Promise<T>); | |
| }; | |
| const request = (baseURL: string) => <T>(path: string, option: Option) => { | |
| return fetch(`${baseURL}${path}`, option).then((res) => res.json() as Promise<T>); | |
| }; | |
| const option = { | ||
| method: HttpMethod.Get, | ||
| }; |
There was a problem hiding this comment.
request 함수의 default 로 설정하면 어떨까요?
There was a problem hiding this comment.
지금은 api 함수가 하나밖에 없지만 확장성을 고려했을때 Get method 타입의 option이 default 옵션은 아니라고 생각했어요!
cors나 header 관련 option이 추가되어야 한다면 그 값이 base가 되는 형식으로 작성되어야 하지 않을까 생각합니다!
| 'module-resolver', | ||
| { | ||
| alias: { | ||
| '^~/(.+)': './src/\\1', |
| const Button: React.FC<ButtonProps> = (props) => { | ||
| const { children, type = 'button', ...rest } = props; | ||
|
|
||
| // eslint-disable-next-line react/button-has-type |
There was a problem hiding this comment.
6줄이 있는데, ESlint 설정을 바꾸는 것보다 주석으로 처리하는 걸 선호하는 이유가 있을까요?!
There was a problem hiding this comment.
전체적인 lint설정은 유지하면서 특정 경우에 한해서만 lint를 disable해주고 싶어서 그랬습니다ㅎㅎ
| }; | ||
|
|
||
| const SearchResult: React.FC<SearchResultProps> = ({ userInfo }) => { | ||
| if (!userInfo) return null; |
There was a problem hiding this comment.
null을 꼭 뱉어야하는 상황이 아니라면 생략해도 좋을 것 같습니다!
There was a problem hiding this comment.
userInfo가 빈값으로 오는 경우가 있을거라고 생각해서 이 라인을 작성해주었는데
생각해보니 user가 존재하지 않는 경우는 404응답이 오고 error 처리를 해주기 때문에 생략하는게 맞는 것 같아요!
감사합니다!! 👍
| <Styled.UserMetadata> | ||
| <div className="user-name">{username}</div> | ||
| <div className="user-repo-stars"> | ||
| {repositories.length} Repositories / {starCount} stars |
| @@ -0,0 +1,31 @@ | |||
| import React, { createContext, useState } from 'react'; | |||
|
|
|||
| export enum PageStatus { | |||
| width: 100%; | ||
|
|
||
| position: absolute; | ||
| top: 30vh; |
There was a problem hiding this comment.
vh 단위를 처음보는데.. 혹시 설명해주실 수 있나요? % 단위와 다른가요?
There was a problem hiding this comment.
뷰포트의 높이값입니다!
브라우저 높이가 만약에 1080px이면 30vh는 1080 * 0.3 px입니다ㅏ
| @@ -0,0 +1,10 @@ | |||
| <!DOCTYPE html> | |||
| <html lang="en"> | |||
| return ( | ||
| <BrowserRouter> | ||
| <Switch> | ||
| <Route path="/search" component={SearchPage} /> |
There was a problem hiding this comment.
루트를 고려못했네요! 감사합니다!!
루트로 접근했을 떄 /search 로 리다이렉트 시키거나,
루트로 path를 변경해주거나 방법은 여러가지일 것 같은데
현재 상황에서 여러 페이지가 존재하는게 아니니 기존의 searct path를 루트로 변경해주는게 좋을 것 같아요!
| import React from 'react'; | ||
| import Loader from 'react-loader-spinner'; | ||
|
|
||
| const LoadingSpinner: React.FC<{ className: string }> = ({ className }) => { |
| const ButtonMemo = React.memo(Button); | ||
|
|
||
| const SearchKeywordBox: React.FC<SearchKeywordBoxProps> = ({ search, initialKeyword }) => { | ||
| const [keyword, setKeyword] = useState<string>(initialKeyword); |
There was a problem hiding this comment.
const SearchKeywordBox: React.FC = ({ search, initialKeyword = '' }) => {
이런 식으로 선언해도 useState에 제네릭을 주어야 하나요?
There was a problem hiding this comment.
윤희님이 말씀하신대로 하면 타입추론이 되어서 제네릭 안넘겨줘도 될 될거에용
|
|
||
| checkHasBeenSearched(); | ||
|
|
||
| await delay(1000); |
There was a problem hiding this comment.
api 요청할 때 로딩 spinner를 보여주고 싶어서 추가했어요!
다른 방법이 있을 것 같은데 모르겠어서 무식하게 setTimeout을 주었답니다...허허
| @@ -0,0 +1 @@ | |||
| defaults | |||
| &:hover { | ||
| background-color: #dcdcdc; | ||
| } | ||
| `; |
There was a problem hiding this comment.
오 👍
지수님 요 순서 다 외우셨나요?? ㅋㅋㅋㅋ
회사에서 맨날 놓쳐서 푸시전에 솔팅 툴 돌리는 1인..
| title: string; | ||
| } | ||
|
|
||
| const BeautifulTitle: React.FC<BeautifulTitle> = ({ title }) => { |
There was a problem hiding this comment.
앜ㅋㅋㅋㅋ 희라님ㅋㅋㅋ 핵웃곀ㅋㅋ
근데 저 섬세함에 감탄하고 갑니다.
| const ButtonMemo = React.memo(Button); | ||
|
|
||
| const SearchKeywordBox: React.FC<SearchKeywordBoxProps> = ({ search, initialKeyword }) => { | ||
| const [keyword, setKeyword] = useState<string>(initialKeyword); |
There was a problem hiding this comment.
윤희님이 말씀하신대로 하면 타입추론이 되어서 제네릭 안넘겨줘도 될 될거에용
| }; | ||
|
|
||
| const handleInputKeyEvent = (e: React.KeyboardEvent<HTMLInputElement>) => { | ||
| if (e.keyCode !== 13) return; |
There was a problem hiding this comment.
오 이런 디테일 매우 좋아요 ㅋㅋㅋㅋ
Enter가 있다는 것은 처음알았네요 👍
because of type inference mash-up-kr-web#7 (comment)
No description provided.