20220207 Frontend 일일 개발일지
===
###### tags: `20220207`
# 개발 내용
## 로딩시 리렌더링 되는 문제 해결.
:::warning
뭔가 SHOP 화면에서 필터링 적용하여 렌더링 시 2번 3번 렌더링 되는 이슈가 있었다.
또한, 홈화면에서 브랜드를 눌렀을때 `/search?keyword=${검색어}` 로 이동했다가, 다시 `/search` 로 이동하는 버그가 있었다.
==바로 검색되는 `/search?keyword=${검색어}`로 가는것이 정상이였지만 말이다.==
:::
- ShopTemplate 화면에서,
```typescript=
useEffect(() => {
const query = queryMaker(
filteredCategory,
filteredBrand.map((brand) => brandId.get(brand)),
filteredCollections,
filteredGender,
filteredPrice,
sortOption,
);
router &&
router.push({
pathname: "/search",
query: query,
});
}, [
luxaryFilter,
filteredCategory,
filteredBrand,
filteredGender,
filteredPrice,
sortOption,
brandId,
]);
```
해당 코드를 통해 필터가 적용되면 `router.push` 를 통해 필터를 적용했다.
#### 문제점이라고 생각한 이유
`/search?keyword=${검색어}`로 이동했을때, 해당 `useEffect`는 무조건 작용하는 것으로 보여졌다.
-> `query` 객체가 비어있을텐데, 불필요하게 해당 `push` 가 작동하는 것이였다.
#### 바꾼 코드
```typescript=
useEffect(() => {
const query = queryMaker(
filteredCategory,
filteredBrand.map((brand) => brandId.get(brand)),
filteredCollections,
filteredGender,
filteredPrice,
sortOption,
);
Object.keys(query).length > 0 &&
router &&
router.push({
pathname: "/search",
query: query,
});
}, [
luxaryFilter,
filteredCategory,
filteredBrand,
filteredGender,
filteredPrice,
sortOption,
brandId,
]);
```
- 간단하게 `query` 객체가 빈 객체가 아닐때 작동하도록 수정하였고, 버그 수정했다.
---
## 드롭다운 박스 `z-index` 관련 문제 해결
작일 `z-index: -1` 로 주어서 해결했지만, 다른 문제가 기다리고 있었다.
#### 문제점

위와 같이 왼쪽에 잘린 상품 그리드에 전체에 `z-index`를 -1로 주었더니,
- 상품 이미지 클릭 불가
- 상품 하단 찜 클릭 불가
==아예 싹다 클릭이 불가능했다..==
#### 해결방법
```typescript=
return (
<>
<SortContent onClick={() => setIsShow(!isShow)}>
{currentSort}
</SortContent>
{isShow && (
<StyledDropdownWrapper onClick={() => setIsShow(false)}>
<DropdownParent>
<DropdownMenu show={isShow} scrolled={scrolled}>
{contents.map((content) => (
<DropdownItem
active={content === currentSort}
key={content}
onClick={() => onHandleCurrentSort(content)}
>
<MainText>{content}</MainText>
<SubText>{subContents[content]}</SubText>
</DropdownItem>
))}
</DropdownMenu>
</DropdownParent>
</StyledDropdownWrapper>
)}
</>
);
```
- 위 컴포넌트가 `Dropdown` 컴포넌트인데, 해당 컴포넌트의 `StyledDropdownWrapper`에 `z-index`를 추가하였다.
```typescript=
const StyledDropdownWrapper = styled.div`
position: fixed;
top: 0;
right: 0;
width: 100%;
height: 100%;
z-index: 100;
`;
```
- `StyledDropdownWrapper` 는 드롭다운이 활성화 되었을때의 드롭다운 바깥 전체 컴포넌트인데, 해당 컴포넌트에게 `z-index` 속성을 추가하여 해결하였다.
---
## 로딩 컴포넌트 추가
### react-loader-spinner 라이브러리를 활용하였다.
#### 왜 해당 라이브러리를 사용하였는가?
- 굳이 스피너를 만들 필요성도 없거니와 로딩 스켈레톤을 사용할 로딩 상태를 판단하는 것이 더 중요하다고 생각하여 외부 라이브러리를 사용하였다.
- `SWR` 를 활용하는 입장에서는 로딩 상태를 판별하는 것이 굉장히 용이하다.
- 이 이유가 `swr`를 선택한 이유기도 하였다.
```typescript=
const {data, error} = useSWR('END_POINT', fetcher);
```
- 위와 같은 코드가 있을때, data값이 false라면 로딩 상태임을 공식문서로 확인 할 수 있다.
- 따라서 필요한 코드는 아래처럼 간단하다.
```typescript=
if(!data) {
return (<Loading />)
}
```
- 단, 위와 같은 코드는 최종 `return` 바로 위에 작성되어야 함을 주의하였다.
---
## 홈 화면 내 찜 아이콘 선택시 버블링 문제 해결.
> 아주 간단한 버그를 해결했다.
```typescript=
const ProductThumbnailImage: FunctionComponent<ProductThumbnailImageProps> = (
props,
) => {
const { imgSrc, backgroundColor, isInWishList, onHandleWishClick } = props;
const onClick = (e) => {
e.preventDefault();
onHandleWishClick();
};
return (
<ProductThumbnailImageWrapper>
{isInWishList ? (
<Icon
onClick={onClick}
name="BookmarkFilled"
style={{ cursor: "pointer", maxWidth: "15px", minWidth: "15px" }}
/>
) : (
<Icon
onClick={onClick}
name="Bookmark"
style={{ cursor: "pointer", maxWidth: "15px", minWidth: "15px" }}
/>
)}
<ProductImage
src={imgSrc}
category="home"
backgroundColor={backgroundColor}
/>
</ProductThumbnailImageWrapper>
);
};
```
- `Icon`에 할당되었던 `onClick` 함수에 `e.preventDefault` 추가로 버블링을 억제하였다~
---
## 검색 기능 활성화
#### 개발 방법
```typescript=
<Icon
name="Magnifier"
style={{ cursor: "pointer" }}
onClick={() => {
Swal.fire({
position: "top",
padding: "1rem",
width: "70%",
icon: "question",
titleText: "검색어를 입력하세요. 🧐",
input: "text",
inputAttributes: {
autocapitalize: "off",
},
showCancelButton: true,
confirmButtonText: "검색",
confirmButtonColor: "black",
cancelButtonText: "취소",
cancelButtonColor: "#909090",
showLoaderOnConfirm: true,
preConfirm: (input) => {
router &&
router.push({
pathname: "search",
query: {
keyword: `${input}`,
},
});
},
});
}}
/>
```
- `HeaderMain` 컴포넌트의 돋보기 아이콘에 해당 코드만 추가하였다.
- 너무 쉽게 완료되어서.. 고민이다.
#### 고민사항
- 왜 굳이 외부 라이브러리로 이를 구현했는가?
- 모달을 이미 작성한 상태에서 다른 형식의 모달을 작성하는것이 현실적인 프로젝트 deadline에 영향을 끼칠 것이라 생각했다.
- 지금 작성하며 고민해보니 가능 할 것 같은 느낌이 들긴한다. 고민을 더 해봐야겠다.