카테고리 없음
무한스크롤 구현하기
jann2
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컴포넌트를 따로 만들어서 작업하시던 것과 비슷하다고 생각했다. 데이터를 어떻게 관리하느냐가 어려운 것 같다.