-
Notifications
You must be signed in to change notification settings - Fork 44
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
[유호민] Week7 #304
The head ref may contain hidden characters: "part2-\uC720\uD638\uBBFC-week7"
[유호민] Week7 #304
Conversation
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.
콤포넌트 구조가 생각보다 괜찮습니다!
몇가지 포인트 짚어보자면 fetch 함수의 에러핸들링을 어디서 하면 좋을지, 콤포넌트 구현 시 어디까지 역할과 책임을 전달하면 좋을지, 그리구 화면에서 사용할 데이터의 상태 (null / loading / available) 에 따라 어떻게 처리할건지 등등이 개선되면 좋겠어요.
이에 대한 내용들은 코드단 리뷰에 남겨두었으니 한번 체크 부탁드립니다.
고생 많으셨어요!
const [user, setUser] = useState({ | ||
id: null, | ||
name: null, | ||
email: null, | ||
profileImageSource: null, | ||
}); |
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.
각 필드마다 null로 두기 보단, user라는 상태를 nullable로 관리하는게 좋아보여요
const [user, setUser] = useState({ | |
id: null, | |
name: null, | |
email: null, | |
profileImageSource: null, | |
}); | |
const [user, setUser] = useState(null) |
const loadUserData = async () => { | ||
let result; | ||
|
||
try { | ||
result = await fetchUserData(); | ||
} catch (error) { | ||
console.error(error); | ||
return; | ||
} | ||
|
||
const { id, name, email, profileImageSource } = result; | ||
|
||
setUser((p) => ({ | ||
...p, | ||
id: id, | ||
name: name, | ||
email: email, | ||
profileImageSource: profileImageSource, | ||
})); | ||
} |
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.
함수가 처리하고 있는 역할이 너무 큽니다!
- 데이터 조회하고
- 에러핸들링 하구
- 상태 업데이트 해주는
이 모든 역할을 한 함수에 구현되어있는데요.
이 보다는, useEffect 내에서 데이터를 불러와 에러핸들링 및 상태 업데이트를 해주는게 조금 더 좋을 것 같아요.
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.
또한 좀 번복적인 형태로 비동기 처리를 하고 있는데요, 이런 형태로 작성되는게 더 좋을 것 같아요!
const loadUserData = async () => { | |
let result; | |
try { | |
result = await fetchUserData(); | |
} catch (error) { | |
console.error(error); | |
return; | |
} | |
const { id, name, email, profileImageSource } = result; | |
setUser((p) => ({ | |
...p, | |
id: id, | |
name: name, | |
email: email, | |
profileImageSource: profileImageSource, | |
})); | |
} | |
const loadUserData = async () => { | |
try { | |
const result = await fetchUserData(); | |
const { id, name, email, profileImageSource } = result; | |
setUser((p) => ({ | |
...p, | |
id: id, | |
name: name, | |
email: email, | |
profileImageSource: profileImageSource, | |
})); | |
} catch (error) { | |
console.error(error); | |
} | |
} |
loadUserData(); | ||
loadFolderData(); |
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.
위 내용대로 업데이트 된다면 이런 형태가 되겠죠?
loadUserData(); | |
loadFolderData(); | |
fetchFolderData() | |
.then(res => setFolders(res.data)) | |
.catch(e => console.error(e)) |
<> | ||
<Navbar user={user} /> | ||
<Profile folderData={folderData} /> | ||
<Routes> | ||
<Route path="/" element={<CardList folderData={folderData} />}></Route> | ||
<Route path="/detail/:id" element={<Detail />}></Route> | ||
</Routes> | ||
<Footer /> | ||
</> |
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.
레이아웃 기능과 라우트 기능이 혼용되어 있는데요. 만약 공통으로 활용되어야 하는 녀석이라면 Outlet이라는 기능을 활용해보는게 좋겠습니다
import SearchImg from '../img/search.svg'; | ||
import { calculateTimeDiff, formatDate } from '../utils'; | ||
|
||
function Card({ link }) { |
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.
한 파일에서는 콤포넌트 하나만 구현해주세요!
또한 Card라는 이름은 카드모양의 UI 콤포넌트인 경우 많이 활용하는 네임이기 때문에
카드 형태인 링크 콤포넌트임을 표현하기 위해 LinkCard
정도의 네이밍이 적합해보입니다!
<> | ||
<div className='card-container'> | ||
<input className="search-bar" type='text' placeholder='링크를 검색해보세요.'></input> | ||
<img className='search-bar-image' alt='magnifying glass' src={SearchImg} /> | ||
<div className="card-list"> | ||
{ | ||
links.map((link) => { | ||
return ( | ||
<Card key={link.id} link={link} /> | ||
) | ||
}) | ||
} | ||
</div> | ||
</div> | ||
</> |
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.
불필요한 react fragment는 제거되는게 좋겠어요!
</div> | ||
</div> | ||
|
||
</> |
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.
react fragment 필요하지 않는 경우엔 제거해주세요!
function Profile({ user }) { | ||
if (user.email) { | ||
return ( | ||
<div className='navbar-profile'> | ||
<img className='navbar-profile-img' alt='profile-img' src={profileImg}></img> | ||
<div className="navbar-user">{user.email}</div> | ||
</div> | ||
) | ||
} else { | ||
return <a className="navbar-login" href="signin.html">로그인</a>; | ||
} | ||
} |
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.
한 파일에는 콤포넌트 하나만 구현해주세요!
또한 이 경우, 사용자 이메일 정보가 없으면 로그인 버튼이 렌더되도록 early return을 활용해보아도 좋겠습니다
function Profile({ user }) { | |
if (user.email) { | |
return ( | |
<div className='navbar-profile'> | |
<img className='navbar-profile-img' alt='profile-img' src={profileImg}></img> | |
<div className="navbar-user">{user.email}</div> | |
</div> | |
) | |
} else { | |
return <a className="navbar-login" href="signin.html">로그인</a>; | |
} | |
} | |
function Profile({ user }) { | |
if (!user.email) { | |
return <a className="navbar-login" href="signin.html">로그인</a>; | |
} | |
return ( | |
<div className='navbar-profile'> | |
<img className='navbar-profile-img' alt='profile-img' src={profileImg}></img> | |
<div className="navbar-user">{user.email}</div> | |
</div> | |
) | |
} |
if (!folderData) { | ||
return <p>Loading...</p> | ||
} |
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.
얘두 로딩처리 상위에서 해주세요!
if (!response.ok) { | ||
throw new Error('정보를 불러오는데 실패했습니다.'); | ||
} |
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.
에러를 던진걸 catch를 해주고 있는데, 이런 형태가 될 필요는 없어보여요!
어차피 외부에서 try catch 작업을 해줄거라면 여기선 try catch를 씌울 필요가 없어보입니다
요구사항
기본
심화
주요 변경사항
스크린샷
멘토에게