[wanted pre onboarding] 4번째 과제: api로 데이터조회 및 메모기능 구현
과제 GitHub: https://github.com/NamgyungKim/wanted-codestates-project-3-8
과제: 충청북도 휴양림 중 마음에 드는 곳에 메모를 남겨 저장하는 서비스를 아래 조건에 맞춰 만들어주세요.
- openAPI를 이용해 데이터 조회를 한다. (한번에10개씩 무한스크롤 구현)
- 조회한 데이터에 메모를 작성할수 있도록한다.
- 작성한 목록의 주소,메모,이름으로 검색이 가능하도록한다.
- 메모는 로컬스토리지에 저장한다.
✨ 무한 스크롤
- api로 불러온 데이터를 스크을 내릴 때마다 요청 하도록 했습니다.
- Throttle을 이용해 이벤트 요청 횟수를 줄였습니다.
const throttle = (callback, delay) => {
let timer = null;
return arg => {
if (timer === null) {
timer = setTimeout(() => {
callback(arg);
timer = null;
}, delay);
}
};
};
const scroll = e => {
if (document.body.offsetHeight < e.target.scrollTop + 700) {
dispatch(getDataFromApi(pageCount));
dispatch(getPageData(pageCount));
}
};
✨ 검색 기능
- 메모, 제목, 주소 원하는 항목을 선택해 검색할 수 있도록 구현 했습니다.
- 타자를 입력할때마다 이벤트를 호출하는 것이 아닌, Debounce를 이용해 일정 시간이 지나면 검색이 되도록 했습니다.
// searchTheme = "메모" || "제목" || "주소" select
// searchContent = 검색text
const placeData = useSelector(state => ({
placeData: state.placeData.placeItems,
})).placeData.filter(item => item[searchTheme].includes(searchContent));
✨ 선택한 장소 저장기능
- 요구사항에 맞춰서 로컬스토리지에 선택한 장소와 메모를 저장해놓고 이를 수정, 삭제하는 방법으로 CRUD를 구현했습니다.
- 로컬스토리지에 데이터를 넣어준 후 store에 넣어주었습니다.
// utils/LocalStorage.js
const setItems = (key, value) =>
localStorage.setItem(key, JSON.stringify(value));
const getItems = key => JSON.parse(localStorage.getItem(key));
const isExist = value => (value ? value : []);
export { setItems, getItems, isExist };
// action
export const savePlaceItem = item => {
const placeItems = getItems('placeItems') || [];
setItems('placeItems', [...placeItems, item]);
return {
type: SAVE_PLACE,
payload: {
item,
},
};
};
export const updatePlaceItem = (memo, index) => {
const placeItems = getItems('placeItems').map((placeItem, i) => {
return i === index ? { ...placeItem, message: memo } : placeItem;
});
setItems('placeItems', placeItems);
return {
type: UPDATE_PLACE,
payload: {
placeItems,
},
};
};
export const deletePlaceItem = removedIdx => {
const placeItems = getItems('placeItems').filter(
(_, idx) => idx !== removedIdx,
);
setItems('placeItems', placeItems);
return {
type: DELETE_PLACE,
payload: {
placeItems,
},
};
};
📚 배운점
- Throttle에 대한 개념을 공부해볼 수 있었다. 이전에 Debounce와 무슨 차이가 있는지 모르겟다. callback 해주는것도 이전에 팀원분이 설명해주신거 듣기는 했지만 당시에도 잘 이해는 가지 않았다. -> 이후 다시 블로그에 정리해보고 직접 코드를 써보니 이해가 갔다. 이번에 codesandbox를 블로그에 넣어본건 처음인데 나중에 다시 찾아서 복붙하기에도 좋고, 작성하면서도 확실히 공부되는 느낌을 받았다.
https://namgyungkim.github.io/javascript/Throttle,-Debounce/ - 이번에 Redux를 사용했는데 솔직히 사용할 필요까지는 없었지만 연습삼아 다른 팀원분들이 구현해 두셨다. Redux까지는 겨우 이해할 수 있지만 thunk는 아직 뭔지 잘 모르겠다. 공부한 후에 다시 한 번 읽어봐야겠다.
- API를 사용하면서 CORS에러가 나왔다. 처음에 그냥 package.json에
"proxy":"http://localhost:3000"
을 통해서 해결한 줄 알았으나, 배포할때 문제가 발생했다. 받은 API가 http여서 netlify 에서 배포가 안될줄 알았는데 그걸 우회하는 다른 방법이 있다고 한다.netlify.toml
에 리다이렉션설정을 해줄 수 있었다. 솔직히 이해는 잘 안간다. http-proxy-middleware가 동작하는 것도, 리다이렉션 해주는 것도..
이건 나중에 공부를 따로 해봐야할 것 같다. - netlify에 배포는 잘됬으나, list에 들어가서 새로고침을 하면 PageNotFound가 떴다.
from = "/*"
를 해주니 해결되었다. SPA이라서 발생했던 문제인 것 같다.
Leave a comment