-
Notifications
You must be signed in to change notification settings - Fork 56
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
[임주민] week8, 11 #392
The head ref may contain hidden characters: "part2-\uC784\uC8FC\uBBFC-week11"
[임주민] week8, 11 #392
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.
뭔가 비슷한 파일이 많다 싶었는데
각각 폴더별로 주차가 나뉘어있었군여...
다음 브랜치에서는 프로젝트 폴더를 하나만 운용하시도록 정리하는게 좋을것같아요
그래야 버전 관리 라는걸 할 수 있습니다
지금은 약간
20241010_과제제출_최종.ppt
20241011_과제제출_최최종.ppt
20241012_과제제출_진짜_최최종.ppt
20241013_과제제출_찐찐막.ppt
이런 느낌이어서 다음 브랜치부터는 최신 폴더 하나만 들고 다니는걸 해보시는게 좋을 것같아요! :-)
links?: Link[]; | ||
} | ||
|
||
export const transCardLinkData = (data: InputData): TransformedData => { |
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.
이 함수의 반환값은 객체이고,
links라는 프로퍼티 안에 map 메서드로 배열이 생성돼요. 그리고 배열안에는 id,createdAt,url,title,description,imageSource 로 구성된 객체가 담깁니다.
코드로 보면
{
links:[
{
id: 숫자값이 들어옵니다,
createdAt: 숫자값이 들어옵니다,
url: 문자열값이 들어옵니다,
title: 문자열값이 들어옵니다,
description: 문자열값이 들어옵니다,
imageSource: 문자열 또는 null 값이들어옵니다,
},
];
}
이런 값 혹은 빈 배열이 반환됩니다.
searchTerm, | ||
selectedFolderName, | ||
}: CardListProps) { | ||
const transformedData = transCardLinkData(cardlinks); |
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.
transCardLinkData 함수로 전달하는 값은 CardList 컴포넌트가 전달받은 props cardlinks 이고, transCardLinkData가 반환한
배열이 transformedData에 담겨요.
selectedFolderName, | ||
}: CardListProps) { | ||
const transformedData = transCardLinkData(cardlinks); | ||
const allLinks: Link[] = transformedData.links ?? []; |
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.
그러면 transformedData가 반환한 값은
{
links:[
{
id: 숫자값이 들어옵니다,
createdAt: 숫자값이 들어옵니다,
url: 문자열값이 들어옵니다,
title: 문자열값이 들어옵니다,
description: 문자열값이 들어옵니다,
imageSource: 문자열 또는 null 값이들어옵니다,
},
];
}
이렇게 생겼어요.
transformedData.links 값이 null 혹은 undefined가 아니면 transformedData.links 값을 allLinks에 할당하고
transformedData.links 값이 null 혹은 undefined라면 [] 빈배열을 allLinks에 할당한다는 의미 입니다.
그래서 allLinks는 Link[] 로 적으면 맞습니다.
여기서 한가지 생각해볼점은, 만약 빈배열을 반환할 수도 있는데 왜 Links[] | [] 가 아니냐 를 생각해볼 수 있습니다.
타입스크립트에서 배열 타입을 선언할 때 Link[]는 "0개 이상의 Link 타입 요소를 포함하는 배열"을 의미합니다.
따라서 빈 배열 []도 Link[] 타입에 속합니다. 타입스크립트에서 배열의 길이에 제한을 두지 않기 때문입니다.
그래서 Link[] 로 타입 선언을 하는게 맞습니다.
const handleSearch = (searchTerm: string) => { | ||
const filtered = allLinks.filter( | ||
link => | ||
(link.folder === selectedFolderName && | ||
link.url.toLowerCase().includes(searchTerm.toLowerCase())) || | ||
(link.title && | ||
link.title.toLowerCase().includes(searchTerm.toLowerCase())) || | ||
(link.description && | ||
link.description.toLowerCase().includes(searchTerm.toLowerCase())) | ||
); | ||
|
||
console.log(filtered); | ||
|
||
setFilteredLinks(filtered); | ||
}; |
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 handleSearch = (searchTerm: string) => { | |
const filtered = allLinks.filter( | |
link => | |
(link.folder === selectedFolderName && | |
link.url.toLowerCase().includes(searchTerm.toLowerCase())) || | |
(link.title && | |
link.title.toLowerCase().includes(searchTerm.toLowerCase())) || | |
(link.description && | |
link.description.toLowerCase().includes(searchTerm.toLowerCase())) | |
); | |
console.log(filtered); | |
setFilteredLinks(filtered); | |
}; | |
const handleSearch = (searchTerm: string) => { | |
const searchTermLower = searchTerm.toLowerCase(); | |
const isMatch = (link: Link) => { | |
const titleMatch = link.title?.toLowerCase().includes(searchTermLower); | |
const descriptionMatch = link.description?.toLowerCase().includes(searchTermLower); | |
const urlMatch = link.url.toLowerCase().includes(searchTermLower); | |
const isInSelectedFolder = link.folder === selectedFolderName; | |
return (isInSelectedFolder && urlMatch) || titleMatch || descriptionMatch; | |
}; | |
const filteredLinks = allLinks.filter(isMatch); | |
console.log(filteredLinks); | |
setFilteredLinks(filteredLinks); | |
}; | |
그리고 filter메서드가 받는 콜백 함수를 기명 함수로 만들어서 전달하면 콜백함수가 어떤 역할을 하는지도 의미가 명확해집니다.
{isModalOpen && modalType === "share" && ( | ||
<Modal isOpen={isModalOpen}> | ||
<ShareFolderModal name={name} onClose={handleCloseModal} /> | ||
</Modal> | ||
)} | ||
{isModalOpen && modalType === "rename" && ( | ||
<Modal isOpen={isModalOpen}> | ||
<RenameFolderModal name={name} onClose={handleCloseModal} /> | ||
</Modal> | ||
)} | ||
{isModalOpen && modalType === "delete" && ( | ||
<Modal isOpen={isModalOpen}> | ||
<DeleteFolderModal name={name} onClose={handleCloseModal} /> | ||
</Modal> | ||
)} |
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.
조건식을 판별하는 함수로 구분해서 반환되는 값에 따라 JSX를 렌더 하는방식으로도 수정할 수 있어요.
{isModalOpen && modalType === "share" && ( | |
<Modal isOpen={isModalOpen}> | |
<ShareFolderModal name={name} onClose={handleCloseModal} /> | |
</Modal> | |
)} | |
{isModalOpen && modalType === "rename" && ( | |
<Modal isOpen={isModalOpen}> | |
<RenameFolderModal name={name} onClose={handleCloseModal} /> | |
</Modal> | |
)} | |
{isModalOpen && modalType === "delete" && ( | |
<Modal isOpen={isModalOpen}> | |
<DeleteFolderModal name={name} onClose={handleCloseModal} /> | |
</Modal> | |
)} | |
const renderModalContent = () => { | |
switch (modalType) { | |
case "share": | |
return <ShareFolderModal name={name} onClose={handleCloseModal} />; | |
case "rename": | |
return <RenameFolderModal name={name} onClose={handleCloseModal} />; | |
case "delete": | |
return <DeleteFolderModal name={name} onClose={handleCloseModal} />; | |
default: | |
return null; | |
} | |
}; | |
return ( | |
...생략 | |
삭제 | |
</button> | |
</> | |
)} | |
</div> | |
{isModalOpen && ( | |
<Modal isOpen={isModalOpen}> | |
{renderModalContent()} | |
</Modal> | |
)} | |
); |
이렇게 하면 JSX부분은 좀더 이해하기 쉬워지고 나중에 조건이 추가되면 switch Case문에서 case만 추가하거나, 수정하기 쉬워지기도 합니다.
links: data.folder.links.map(item => ({ | ||
id: item.id, | ||
createdAt: item.createdAt, | ||
url: item.url, | ||
title: item.title, | ||
description: item.description, | ||
imageSource: item.imageSource || 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.
links: data.folder.links.map(item => ({ | |
id: item.id, | |
createdAt: item.createdAt, | |
url: item.url, | |
title: item.title, | |
description: item.description, | |
imageSource: item.imageSource || null, | |
})), | |
links: data.folder.links.map(({id,createdAt,url,title,description,imageSource}) => ({ | |
id, | |
createdAt, | |
url, | |
title, | |
description, | |
imageSource: imageSource || null, | |
})), |
구조분해할당을 활용하면 반복되는 item이라는 프로퍼티에서 한depth 더 들어가지 않고 바로 원하는 프로퍼티에 접근할 수 있습니다.
그리고 프로퍼티의 key, value가 같다면 단축 속성명 이라는 문법으로도 한번 더 줄일 수 있어요
이렇게 해야해요! 가 아닌, 이런 방법도 있다~ 알고계시면 좋다~ 입니다 :-)
요구사항
기본
심화
주요 변경사항
멘토에게