치춘짱베리굿나이스
[프리온보딩] 220524 그룹과제 #3 본문
그룹과제 #3
공식적인 내생각
내 파트에서 할 수 있는 건 다 해서 추가 기능을 구현했다
광고 만들기 버튼을 누르면 진짜로 광고를 만들 수 있게 만들고 싶었는데 어찌저찌 작성하다보니…. 기본내용 구현보다 광고추가 기능 하나가 더 빡셌던 것 같다
중간중간 컴포넌트 분리나 합치기 등 리팩토링도 해가면서 했더니 밤을 꼴닥 새버렸다
하하
작업 내용
숫자 3자리마다 쉼표 찍어주기 - toLocaleString()
const number = 1234;
number.toLocaleString(); // 1,234
이렇게 쉬울수가
정규식은 다시 잊어버리도록 해야겠다
프로그래머 최악의 적 정규식
인자를 추가함으로써 숫자를 아라비아어, 한자 등 특정 언어로 바꾸거나 스타일을 추가할 수 있다 (달러, 엔화, 한화 등…)
promise랑 친구먹음
export const getAdListData = () => {
const promise = new Promise((resolve: (value: IAdData) => void, reject) => {
const data: IAdData = store.get('adsData')
if (!data) reject();
else resolve(data);
})
return promise
.then(setFetchDelayPromise(500))
.then((data: IAdData) => data)
.catch(() =>
axios
.get('/wanted_FE_ad-list-data-set.json')
.then(setFetchDelay(500))
.then((response: AxiosResponse) => response.data)
);
};
원래는 axios로 데이터 받고 바로 필터링까지 진행했는데, 데이터를 추가하려 하니 필터링을 거치지 않은 원본 데이터가 필요해서 + 로컬 스토리지에 데이터 넣었다 빼는 부분이 필요해서 fetch 함수 (getAdListData
)를 개조했다
그와중에 store.get
을 먼저 진행하고, 로컬 스토리지에 데이터가 존재하지 않을 경우에만 axios로 데이터를 받아와야 하기 때문에 promise
+ then
/ catch
를 이용했다
로컬 스토리지에 데이터가 없었을 경우 reject
를, 존재했을 경우 resolve
를 통해 데이터 fetching 성공 여부를 결정하고, 실패했을 경우 (reject
) catch 문을 통해 axios
로 데이터를 받을 수 있도록 하였다
이중 Promise
문이 되긴 했는데 어차피 useQuery
훅에서 사용하려면 Promise
형태여야 해서 (+ 지정한 동작이 끝날 때까지 기다리고 성공, 실패 여부에 따라 쉽게 추가 동작을 구현할 수 있어서) Promise
를 사용했고 결과는 매우 괜찮았다
로컬 스토리지에 데이터가 없을 경우 예외처리를 복잡하게 하지 않고 바로 axios로 넘어갈 수 있기도 하고, 과제에서 요구한 delay도 쉽게 넣을 수 있어서 매우 쓸만하다
const filter = new Promise<IAdData>((resolve) => {
if (adsFilterIndex === 0) resolve(data);
const newData: IAdData = {
count: 0,
ads: [],
}
newData.ads = data.ads.filter((ad: IAd) => ad.status === STATUS[adsFilterIndex]);
newData.count = newData.ads.length;
resolve(newData);
});
filter.then((newData) => setFilteredData(newData));
커스텀 훅 내에서 필터링을 수행할 때도 Promise를 사용했다
이번에는 필터링이 끝난 데이터를 filteredData
상태에 넣어야 했기 때문
setState
가 비동기로 동작하기 때문에 동작 관리를 해주지 않으면 그냥 빈 데이터가 홀랑 들어가버린다
그걸 막기 위해 then
을 사용해서 후속동작으로만 필터링 데이터를 설정할 수 있게 해 주었고, 어차피 예외처리할 요인은 없으니 resolve
만 사용하였다
Promise
가 쓸 때마다 조금씩 헷갈려서 매번 문서 찾아가면서 하긴 하는데 그래도 많이 익숙해진듯하다
Promise 내에서 then으로 고의 딜레이 주기
export const setFetchDelay = (ms: number) => {
return (x: AxiosResponse) => {
return new Promise<AxiosResponse>((resolve) => {
setTimeout(() => resolve(x), ms);
});
};
};
export const setFetchDelayPromise = (ms: number) => {
return (x: IAdData) => {
return new Promise<IAdData>((resolve) => {
setTimeout(() => resolve(x), ms);
});
};
};
과제 요구사항 중 로딩 화면을 구현하고 이를 위해 임의로 딜레이를 주어야 하는 부분이 있었다
결과값이 AxiosResponse
일 때 (데이터 받아올 때 axios 쓴 경우) 와 IAdData
일 때 (로컬 스토리지에서 가져왔을 때) 를 다르게 구현했다
유니온타입을 사용해서 AxiosResponse일수도 IAdData일 수도 있습니다
라고 합쳐서 작성하면 해당 타입의 인수로 할당할 수 없다면서 오류가 나더라
axios.get().then(setFetchDelay(500)).then((res) => res.data);
// setFetchDelay가 반환하는 함수를 합친 모습
axios.get().then((x: AxiosResponse) => {
return new Promise<AxiosResponse>((resolve) => {
setTimeout(() => resolve(x), 500);
});
}).then((res) => res.data);
사용 방법은 위와 같다
setFetchDelay
에 인자로 500을 넣으면, 반환값은 아래와 같이 Promise
를 사용하는 함수가 된다
Promise
에 의해 setTimeout
으로 500ms를 쉬어주고, 다 쉬고 나면 인자로 받은 x
를 resolve
함수를 통해 그대로 반환해주는 형식
따라서 axios.get
에서 받은 인자를 그대로 (res) ⇒ res.data
까지 가져와서 사용할 수 있다
비동기 처리가 이렇게 간단하다
조건부 렌더링 (&& 연산자 등) / display: none
- 조건부 렌더링: 조건의 true / false 여부가 바뀔 때마다 리렌더링되므로, 상태값도 초기화된다
- 따라서 form 등 내용물의 초기화가 필요할 때 사용하면 좋다
display: none
: 렌더링은 계속 되어있는 상태에서 스타일로 숨김 / 공개 처리만 하는 것이기 때문에 내용물 및 상태값도 그대로 남아있다- 내용물의 초기화가 필요 없거나, 값을 유지하고 싶을 때 사용하면 좋다
아무 생각 없이 display: none
을 썼더니 form
안의 내용물이 계속 남아있어서…. 아예 리렌더링을 반복하는 방식을 사용했다
useEffect
에 dependency
로 isOpen
상태값을 걸어줄까 했는데 form
안에서 사용하는 상태값이 너무 많아서 일일히 초기화하는 것도 일이다
일일히 일이다
'프로젝트 > 원티드 프리온보딩' 카테고리의 다른 글
[프리온보딩] 220526 그룹과제 #3 종료 + 그룹과제 #4 (0) | 2022.05.27 |
---|---|
[프리온보딩] 220525 그룹과제 #3 (0) | 2022.05.26 |
[프리온보딩] 220523 그룹과제 #3 (0) | 2022.05.24 |
[프리온보딩] 220517 강의 메모 02 (코드 예시) (0) | 2022.05.23 |
[프리온보딩] 220521 그룹과제 #2 종료 + 그룹과제 #3 (0) | 2022.05.23 |