From 182e7513871c98332d657ad751c6f1b0c07803aa Mon Sep 17 00:00:00 2001 From: yongaricode Date: Wed, 14 May 2025 12:32:08 +0900 Subject: [PATCH 1/3] =?UTF-8?q?refactor:=20=EB=B6=88=ED=95=84=EC=9A=94?= =?UTF-8?q?=ED=95=9C=20=EA=B2=80=EC=83=89=EC=96=B4=20=EC=A0=80=EC=9E=A5=20?= =?UTF-8?q?API=20=ED=98=B8=EC=B6=9C=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/booksnap.api.ts | 15 --------------- src/components/Header/BookSearchHeader.tsx | 2 -- 2 files changed, 17 deletions(-) diff --git a/src/api/booksnap.api.ts b/src/api/booksnap.api.ts index 3938b1e..140c6f1 100644 --- a/src/api/booksnap.api.ts +++ b/src/api/booksnap.api.ts @@ -128,21 +128,6 @@ export const searchReview = async (bookName: string) => { } }; -// 책 검색 기록 저장 -export const postSearchHistory = async (searchType: string, searchWord: string) => { - try { - const response = await instance.post(`/api/search-history`, { - searchType: searchType, - searchWord: searchWord, - }); - if (response.status === 200) { - return response.data; - } - } catch (err) { - console.log(err); - } -}; - // 최근 검색어 불러오기 export const getRecentSearch = async (searchtype: string, page: number, size: number) => { try { diff --git a/src/components/Header/BookSearchHeader.tsx b/src/components/Header/BookSearchHeader.tsx index c289135..f3bf5fd 100644 --- a/src/components/Header/BookSearchHeader.tsx +++ b/src/components/Header/BookSearchHeader.tsx @@ -3,7 +3,6 @@ import Arrow from '../../../public/icons/menu-bar/ArrowLeft.svg?react'; import { useNavigate } from 'react-router-dom'; import SearchBar from '../Zip/SearchBar'; -import { postSearchHistory } from '../../api/booksnap.api'; const BookSearchHeader = () => { const [searchWord, setSearchWord] = useState(''); @@ -11,7 +10,6 @@ const BookSearchHeader = () => { const handleSearch = () => { nav(`/booksnap?query=${searchWord}`); - postSearchHistory('booktitle', searchWord); }; return ( From efdcf21fc477f2b5cd64913ca30cab96d8aedada Mon Sep 17 00:00:00 2001 From: yongaricode Date: Wed, 14 May 2025 13:05:43 +0900 Subject: [PATCH 2/3] =?UTF-8?q?fix:=20=EB=B6=81=EC=8A=A4=EB=83=85=20?= =?UTF-8?q?=EA=B2=80=EC=83=89=20UI=20=EC=88=98=EC=A0=95=20=EB=B0=8F=20?= =?UTF-8?q?=EC=8A=A4=ED=81=AC=EB=A1=A4=20=ED=8A=95=EA=B8=B0=EB=8A=94=20?= =?UTF-8?q?=EB=AC=B8=EC=A0=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Header/BookSearchHeader.tsx | 10 ++-- src/pages/Booksnap/BookSnap.tsx | 55 +++++++++++----------- 2 files changed, 34 insertions(+), 31 deletions(-) diff --git a/src/components/Header/BookSearchHeader.tsx b/src/components/Header/BookSearchHeader.tsx index f3bf5fd..b6019ca 100644 --- a/src/components/Header/BookSearchHeader.tsx +++ b/src/components/Header/BookSearchHeader.tsx @@ -4,8 +4,12 @@ import Arrow from '../../../public/icons/menu-bar/ArrowLeft.svg?react'; import { useNavigate } from 'react-router-dom'; import SearchBar from '../Zip/SearchBar'; -const BookSearchHeader = () => { - const [searchWord, setSearchWord] = useState(''); +interface BookSearchHeaderProps { + query?: string; +} + +const BookSearchHeader = ({ query }: BookSearchHeaderProps) => { + const [searchWord, setSearchWord] = useState(query || ''); const nav = useNavigate(); const handleSearch = () => { @@ -14,7 +18,7 @@ const BookSearchHeader = () => { return (
- nav(-1)} /> + nav('/booksnap')} /> { const [filter, setFilter] = useState('createdAt'); const [review, setReview] = useState([]); const [page, setPage] = useState(1); - const [isLast, setIsLast] = useState(false); - const [isBottom, setIsBottom] = useState(false); - const isLastRef = useRef(false); + const [isLast, setIsLast] = useState(false); const [isLoading, setIsLoading] = useState(false); + const isLastRef = useRef(false); const mainRef = useScrollRef(); const [searchParams] = useSearchParams(); const query = searchParams.get('query'); - useEffect(() => { - if (query) { - searchReview(query).then((data) => { - setReview(data.booksnapPreview); - }); - } - }, [query]); - // 리뷰 목록 받아오기 const getReviews = async () => { setIsLoading(true); @@ -37,7 +29,6 @@ const BookSnap = () => { const data = await getReview(filter, page); setReview((prev) => (page === 1 ? data.data.booksnapPreview : [...prev, ...data.data.booksnapPreview])); setIsLast(data.data.last); - setIsBottom(false); } catch (error) { console.error('리뷰를 불러오는 중 에러 발생:', error); } finally { @@ -45,12 +36,22 @@ const BookSnap = () => { } }; - // filter가 변경될 때 상태 초기화 및 getReviews 호출 + // 검색어 있을 때는 검색 API 호출 + useEffect(() => { + setReview([]); + if (query) { + searchReview(query).then((data) => { + setReview(data.booksnapPreview); + }); + } else { + getReviews(); + } + }, [query]); + useEffect(() => { if (query) return; setReview([]); setIsLast(false); - setIsBottom(false); if (page !== 1) { setPage(1); // page가 1이 아니면 1로 초기화 (getReviews는 page가 바뀔 때 호출됨) @@ -59,28 +60,26 @@ const BookSnap = () => { } }, [filter]); - // page가 변경될 때만 getReviews 호출 + // page가 바뀌면 getReviews 호출 useEffect(() => { if (query) return; - - if (page !== 1 || review.length === 0) { - // 🔄 리뷰가 없거나 페이지가 1이 아닐 때만 호출 - getReviews(); - } + getReviews(); }, [page]); - // isLast 업데이트 시 참조 업데이트 + // isLast 상태를 ref에도 반영 useEffect(() => { isLastRef.current = isLast; }, [isLast]); + // 스크롤 이벤트 등록 useEffect(() => { const handleScroll = () => { if (!mainRef.current) return; const { scrollTop, clientHeight, scrollHeight } = mainRef.current; - if (scrollTop + clientHeight >= scrollHeight - 100 && !isBottom && !isLastRef.current) { - setIsBottom(true); + const nearBottom = scrollTop + clientHeight >= scrollHeight - 100; + + if (nearBottom && !isLastRef.current && !isLoading) { setPage((prev) => prev + 1); } }; @@ -93,9 +92,9 @@ const BookSnap = () => { return () => { el?.removeEventListener('scroll', handleScroll); }; - }, [mainRef, isBottom]); + }, [mainRef, isLoading]); - if (isLoading) { + if (isLoading && review.length === 0) { return ; } @@ -106,9 +105,9 @@ const BookSnap = () => { return (
{/* 헤더 */} - -
- + {query ? : } +
+ {!query && }
{review.map((preview, index) => ( From 839f6a6ea91892708b5b4a800a653cb64120d5b0 Mon Sep 17 00:00:00 2001 From: yongaricode Date: Wed, 14 May 2025 13:14:11 +0900 Subject: [PATCH 3/3] =?UTF-8?q?feat:=20=EB=B6=81=EC=8A=A4=EB=83=85=20?= =?UTF-8?q?=EC=B5=9C=EA=B7=BC=20=EA=B2=80=EC=83=89=EC=96=B4=20=EB=88=84?= =?UTF-8?q?=EB=A5=B4=EB=A9=B4=20=EA=B2=80=EC=83=89=EC=B0=BD=EC=97=90=20?= =?UTF-8?q?=EB=B0=98=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Booksnap/RecentSearch.tsx | 5 +++-- src/components/Header/BookSearchHeader.tsx | 11 ++++++++--- src/pages/Booksnap/BookSearch.tsx | 9 +++++++-- 3 files changed, 18 insertions(+), 7 deletions(-) diff --git a/src/components/Booksnap/RecentSearch.tsx b/src/components/Booksnap/RecentSearch.tsx index bf0697a..ae0dc22 100644 --- a/src/components/Booksnap/RecentSearch.tsx +++ b/src/components/Booksnap/RecentSearch.tsx @@ -3,11 +3,12 @@ import { IoTrashSharp } from 'react-icons/io5'; interface RecentSearchProps { name: string; + onClick: (book: string) => void; } -const RecentSearch = ({ name }: RecentSearchProps) => { +const RecentSearch = ({ name, onClick }: RecentSearchProps) => { return ( -
+
onClick(name)}>

{name}

diff --git a/src/components/Header/BookSearchHeader.tsx b/src/components/Header/BookSearchHeader.tsx index b6019ca..9b02bf4 100644 --- a/src/components/Header/BookSearchHeader.tsx +++ b/src/components/Header/BookSearchHeader.tsx @@ -1,6 +1,5 @@ -import { useState } from 'react'; +import { useEffect, useState } from 'react'; import Arrow from '../../../public/icons/menu-bar/ArrowLeft.svg?react'; - import { useNavigate } from 'react-router-dom'; import SearchBar from '../Zip/SearchBar'; @@ -12,6 +11,12 @@ const BookSearchHeader = ({ query }: BookSearchHeaderProps) => { const [searchWord, setSearchWord] = useState(query || ''); const nav = useNavigate(); + useEffect(() => { + if (query !== undefined) { + setSearchWord(query); + } + }, [query]); + const handleSearch = () => { nav(`/booksnap?query=${searchWord}`); }; @@ -24,7 +29,7 @@ const BookSearchHeader = ({ query }: BookSearchHeaderProps) => { setSearchWord={setSearchWord} onSearch={handleSearch} text="책 제목으로 리뷰를 찾아보세요!" - > + />
); }; diff --git a/src/pages/Booksnap/BookSearch.tsx b/src/pages/Booksnap/BookSearch.tsx index 7b2b6e3..a2be2e5 100644 --- a/src/pages/Booksnap/BookSearch.tsx +++ b/src/pages/Booksnap/BookSearch.tsx @@ -12,6 +12,7 @@ interface RecentType { const BookSearch = () => { const bookname = ['구원의 날', '지구에서 한아뿐', '사이키쿠스오']; const [recent, setRecent] = useState([]); + const [word, setWord] = useState(''); useEffect(() => { getRecentSearch('booktitle', 1, 10).then((data) => { @@ -19,10 +20,14 @@ const BookSearch = () => { }); }, []); + const handleClick = (bookName: string) => { + setWord(bookName); + }; + return (
{/* 헤더 */} - +
{/* 인기 검색어 */}
@@ -38,7 +43,7 @@ const BookSearch = () => {

최근 검색

{recent.map((book, index) => ( - + handleClick(book.searchWord)} /> ))}