-
무한스크롤 구현하기카테고리 없음 2022. 1. 12. 23:24
지난번에 공부했던 react-infinite-scroll-component를
우리 프로젝트의 검색페이지에 적용시켜 보았다.
import React from "react"; import styled from "styled-components"; import InfiniteScroll from "react-infinite-scroll-component"; import { useEffect, useState, useRef } from "react"; import Track from "../../components/mypage/Track"; import { useLocation } from "react-router-dom"; import { apis } from "../../shared/api"; import Header from "../../components/category/Header"; import { Container } from "../../elements/index"; import search, { actionCreators as searchActions, } from "../../redux/modules/search"; import { useDispatch, useSelector } from "react-redux"; import { RiArrowLeftSLine } from "react-icons/ri"; import { HiOutlineSearch } from "react-icons/hi"; const KeywordSearch = (props) => { const dispatch = useDispatch(); const trackWrapRef = useRef(null); const location = useLocation(); const keyword = location.state.value; const search_list = useSelector((state) => state.search.search_list); console.log("search_list", search_list); const [items, setItems] = useState([]); const [hasMore, setHasMore] = useState(true); const [page, setPage] = useState(2); useEffect(() => { //데이터 가져오기 const getsearchList = async (keyword, pages, track) => { const res = await apis.search( (keyword = location.state.value), (pages = 1), (track = 12) ); const data = await res.data.tracks; //리스폰스를 const data에 저장 setItems(data); //items는 현재 빈배열. 여기에 처음 12개 데이터를 set해주기 }; getsearchList(); }, []); const fetchSearch = async (keyword, pages, track) => { console.log("page", page); const res = await apis.search( (keyword = location.state.value), (pages = `${page}`), (track = 12) ); const data = await res.data.tracks; return data; }; const fetchData = async () => { const searchFormServer = await fetchSearch(); setItems([...items, ...searchFormServer]); if (searchFormServer.length === 0 || searchFormServer.length < 12) { setHasMore(false); } setPage(page + 1); }; console.log("items", items); const inputRef = React.useRef(); const handleSearch = () => { const value = inputRef.current.value; if (value.length < 2) { window.alert("검색어를 두 글자 이상 입력해주세요OAO!"); } // else { // dispatch(searchActions.getSearchDB(value)); // } }; useEffect(() => { handleSearch(); }, []); const onClick = () => { handleSearch(); }; const onKeyPress = (event) => { if (event.key === "Enter") { handleSearch(); } }; return ( <div> {items && items.length > 0 ? ( <> <InfiniteScroll dataLength={items.length} next={fetchData} hasMore={hasMore} loader={<h4>Loading...</h4>} endMessage={ <p style={{ textAlign: "center" }}> <b>Yay! You have seen it all</b> </p> } > <Header topMenu /> <Container> <Flex> <Flex onClick={() => { props.history.push("/searchKeyword"); }} > <RiArrowLeftSLine size="30" cursor="pointer" ></RiArrowLeftSLine> </Flex> <Multiline ref={inputRef} onKeyPress={onKeyPress} placeholder="검색어를 두글자 이상 입력해주세요." type="text" defaultValue={keyword} ></Multiline> <HiOutlineSearch size="30" cursor="pointer" onClick={onClick} ></HiOutlineSearch> </Flex> </Container> <Grid> <TrackGrid ref={trackWrapRef}> {items.map((l) => { return ( <TrackDiv key={l.trackId}> <Track {...l} trackWrapRef={trackWrapRef.current} /> </TrackDiv> ); })} </TrackGrid> </Grid> </InfiniteScroll> </> ) : ( <> <Header topMenu /> <Container> <Flex> <Flex onClick={() => { props.history.push("/searchKeyword"); }} > <RiArrowLeftSLine size="30" cursor="pointer"></RiArrowLeftSLine> </Flex> <Multiline ref={inputRef} onKeyPress={onKeyPress} placeholder="검색어를 두글자 이상 입력해주세요." type="text" defaultValue={keyword} ></Multiline> <HiOutlineSearch size="30" cursor="pointer" onClick={onClick} ></HiOutlineSearch> </Flex> <OAODiv> <OAOText>검색결과가 없습니다</OAOText> <OAOText>다시 한번 검색해주세요!</OAOText> <OAO></OAO> </OAODiv> </Container> </> )} </div> ); }; const Flex = styled.div` display: flex; align-items: center; vertical-align: center; `; const Multiline = styled.input` border: none; background: none; border-bottom: solid 3px #ddd; padding: 12px 4px; width: 100%; color: #fff; :focus { border: none; background: none; border-bottom: solid 3px var(--point-color); } `; const Grid = styled.div` padding-left: 10px; /* @media screen and (max-width: 375px) { padding-left: 0px; } */ `; const TrackGrid = styled.div` max-width: 425px; width: 100%; margin: auto; display: flex; flex-wrap: wrap; `; const TrackDiv = styled.div` margin: 0px 10px; @media screen and (max-width: 375px) { margin: 0 5px; } @media screen and (max-width: 320px) { margin: 0 1px; } `; const OAODiv = styled.div` position: relative; margin-top: 120px; `; const OAOText = styled.p` font-size: 14px; text-align: center; margin-bottom: 12px; `; const OAO = styled.div` width: 156px; height: 156px; margin: 40px auto 0px auto; background-image: url("/assets/images/OAO.png"); background-repeat: no-repeat; background-size: cover; `; export default KeywordSearch;
데이터는 잘 받아와지고 무한스크롤도 잘 되고있는데
문제는 검색을 한번만 하는 것은 아니라는 것...
의문
1. 검색을 다시 하게되면 겹치는 데이터가 발생하진 않을까?
=> 리덕스로 데이터를 관리해보기로 했다.(페이징 처리도 리덕스에서 해보기로 함)
2. 현재 상세페이지를 들어갔다 나오면 reload가 되고 있는데 reload가 되면서 1페이지로 가게되는 문제점
(사용자가 보던 페이지가 사라지고 스크롤이 제일 상단으로 가게된다.)
=> 상세페이지 기능을 담당 해주신 용성님이 reload를 없애주기로 했다.
회고
무한스크롤 자체는 생각보다 어렵지 않았다. 예전 강의에서 튜터님이 infinitescoll컴포넌트를 따로 만들어서 작업하시던 것과 비슷하다고 생각했다. 데이터를 어떻게 관리하느냐가 어려운 것 같다.