-
[고양이 사진 검색 사이트] 스크롤 페이지 구현, 랜덤 고양이 배너 section,EventDelegationReact/과제 테스트 2023. 8. 7. 13:59
프로그래머스 과제 테스트 준비
프로그래머스는 html,css, javaScript이기 때문에 실질적으로 도움이 될 만한 React로 준비했다.
테스팅에 목적이 아닌 학습을 위한 구현자료로써, 디자인은 하지 않았고 기능에 초점을 두었다.
🐇 스크롤 페이징 구현
유저가 스크롤바 끝가지 이동 시 다음페이지 로딩하도록 만들어야 한다
1. api 호출시 page 추가
export const getSearchCatData = async (keyword, pages) => {return fetchData(`${API_ENDPOINT}/api/cats/search?q=${keyword}&page=${pages}`);};2. 현재 page state로 관리
const [currentPages, setCurrentPages] = useState(1);3. 스크롤 이벤트 함수 구현
// 스크롤 이벤트 처리 함수const handleScroll = () => {// 브라우저의 스크롤 위치와 문서의 전체 높이를 비교하여 끝까지 도달했는지 체크const { scrollTop, clientHeight, scrollHeight } = document.documentElement;if (scrollTop + clientHeight >= scrollHeight - 10) {// 끝까지 도달하면 다음 페이지를 로딩loadMoreCats();}};4. 스크롤시 api 호출
// 스크롤 페이징 구현const loadMoreCats = async () => {if (isLoading) return;setIsLoading(true);try {const response = await getSearchCatData(keyword, currentPages + 1);const newCatsList = response.data;setCatsList([...catsList, ...newCatsList]);setCurrentPages(currentPages + 1);} catch (error) {console.error('Error while loading more cats:', error);} finally {setIsLoading(false);}};5. 페이지 진입시 스크롤 이벤트 리스너 추가
useEffect(() => {// 컴포넌트가 처음 렌더링 될 때 스크롤 이벤트 리스너를 추가window.addEventListener('scroll', handleScroll);return () => {window.removeEventListener('scroll', handleScroll);};}, []);🐇 랜덤고양이 배너 섹션
- 현재 검색 결과 목록 위에 배너형태의 랜덤 고양이 섹션을 추가한다.
- 앱이 구동될 때 /api/cats/random50 api요청 이후 받은 결과를 별도 섹션에 노출
- 겸색결과가 많더라도 화면에 5개만 노출하여 각 이미지는 좌,우 슬라이등 버튼을 가진다
- 좌, 우 버튼을 클릭하면, 현재 노출된 이미지는 사라지고, 이전 또는 다음 이미지를 보여준다. 트랜지션은 선택이다
1. randomCatBanner 컴포넌트 생성
import React, { useEffect, useState } from 'react';import { getRandomCatData } from '../api/api';import styled from 'styled-components';import Loading from './Loading';import SlideShow from './SlideShow';
const BannerContainer = styled.section`display: flex;justify-content: center;align-items: center;padding: 20px;`;
const RandomCatBanner = ({ isDarkMode }) => {const [isLoading, setIsLoading] = useState(true);const [randomCats, setRandomCats] = useState([]);
useEffect(() => {const fetchRandomCats = async () => {try {setIsLoading(true);const response = await getRandomCatData();setRandomCats(response.data);setIsLoading(false);} catch (error) {console.error('Error while fetching random cats:', error);setRandomCats([]);}};
fetchRandomCats();}, []);
if (isLoading) return <Loading isDarkMode={isDarkMode} />;return (<BannerContainer>{randomCats && (<SlideShow catsList={randomCats.slice(0, 5)} isDarkMode={isDarkMode} />)}</BannerContainer>);};
export default RandomCatBanner;2. SlideShow 컴포넌트 생성
import React, { useState } from 'react';import styled from 'styled-components';
const SlideShowContainer = styled.article`display: flex;align-items: center;overflow: hidden;background-color: ${({ isDarkMode }) => (isDarkMode ? 'black' : 'white')};border-radius: 5%;`;
const SlideShowItem = styled.img`width: 200px;height: 200px;margin: 0 5px;transition: transform 0.3s ease-in-out;border-radius: 20%;`;
const SlideShowButton = styled.button`background-color: transparent;border: none;font-size: 20px;cursor: pointer;`;
const SlideShow = ({ catsList, isDarkMode }) => {const [currentIndex, setCurrentIndex] = useState(0);
const handlePrev = () => {setCurrentIndex((prevIndex) =>prevIndex === 0 ? catsList.length - 1 : prevIndex - 1);};
const handleNext = () => {setCurrentIndex((prevIndex) =>prevIndex === catsList.length - 1 ? 0 : prevIndex + 1);};
return (<SlideShowContainer><SlideShowButton onClick={handlePrev}>❮</SlideShowButton><SlideShowItemkey={catsList[currentIndex].id}src={catsList[currentIndex].url}alt={catsList[currentIndex].id}title={catsList[currentIndex].name}loading="lazy"/><SlideShowButton onClick={handleNext}>❯</SlideShowButton></SlideShowContainer>);};
export default SlideShow;🐇 추가 요구사항
🥕 SearchResult에 각 아이템을 클릭하는 이벤트를 EventDelegation을 이용하여 수정
※ 이벤트 위임(Event Delegation)
JavaScript의 대부분 이벤트는 이벤트 흐름(Event Flow)의 이벤트 캡처링, 이벤트 버블링 단계를 거칩니다. 일반적으로 addEventListener() 메서드의 세 번째 매개변수로 true를 전달하지 않은 이상 이벤트 캡처링 단계는 수행되지 않고 이벤트 버블링 단계를 거치는데, 이벤트 버블링은 타겟에서 이벤트가 발생하면 타겟에서 위로 이벤트를 전파하는 것을 말합니다.
1. img click -> container click
<S.ImgContainer onClick={handleItemClick}>{catsList.map((v, i) => (<S.Imgloading="lazy"src={v.url}key={i}alt={v.id}title={v.name}//이전 : onClick={() => displayModal(v.id)} />/>))}</S.ImgContainer>2. img 클릭 이벤트 생성
// Event delegation 함수const handleImgClick = (event) => {const clickedImage = event.target.closest('img');if (clickedImage) {const id = clickedImage.getAttribute('alt');displayModal(id);}};🥕 각 컴포넌트의 내부함수와 Util함수를 잘게 나누기
component / utils 함수 (api) 구별
'React > 과제 테스트' 카테고리의 다른 글
[Input 이벤트] input readonly, 백스페이스 기능 (0) 2023.08.08 [Input 이벤트] 포커스 이벤트, 영역 외부 클릭시 상태 변화, document.addEventListener (0) 2023.08.08 [고양이 사진 검색 사이트] - 이미지 상세 보기 모달 : 모달, keypress, fade in/out (0) 2023.08.07 [고양이 사진 검색 사이트] 검색 페이지 - autofocus, Loading, api 연결, try & catch, async, await,img title (0) 2023.08.07 [고양이 사진 검색 사이트] HTML, CSS - 시맨틱, media query, 다크모드(dark mode) (0) 2023.08.07