책 형태의 네비게이션 효과 - Part2 검색어 검색 기능 추가

Project Diary/React + Firebase (Snack ShoppingMall)

책 형태의 네비게이션에서 검색어를 입력하여 해당 페이지로 이동하는 기능을 추가하는 방법 기록


 

 

1.  검색 컴포넌트 만들기

먼저 검색 기능을 구현하는 SnackSearch 컴포넌트를 작성합니다

// 검색 컴포넌트 정의
const SnackSearch = ({ onSearch }) => {
  const [searchValue, setSearchValue] = useState(""); // 검색어 상태

  const handleInputChange = (e) => {
    setSearchValue(e.target.value); // 검색어 상태 업데이트
  };

  const onClick = () => {
    handleSearch(); // 검색 버튼 클릭 시 검색 함수 호출
  };

  const onKeyPress = (e) => {
    if (e.key === "Enter") {
      handleSearch(); // 엔터 키 입력 시 검색 함수 호출
    }
  };

  const handleSearch = () => {
    if (searchValue.length >= 1) {
      onSearch(searchValue); // 검색어가 입력된 경우 부모 컴포넌트로 검색어 전달
      setSearchValue(""); // 입력 필드 초기화
    }
  };

  return (
    <SnackSearchBlock>
      <h2>과자 정보</h2>
      <input
        type="search"
        placeholder="과자를 검색하세요"
        value={searchValue}
        onChange={handleInputChange}
        onKeyPress={onKeyPress}
      />
      <button type="button" onClick={onClick}>
        검색
      </button>
    </SnackSearchBlock>
  );
};

export default SnackSearch;

여기서 SnackSearch 컴포넌트는 검색어 입력을 받고, 엔터키를 누르거나 검색 버튼을 클릭했을 때 검색어를 부모 컴포넌트로 전달하는 역할을 합니다.

 

 

2. 검색 기능을 SnackList에 추가하기

이제 SnackList 컴포넌트에서 검색어를 받아 해당 페이지로 이동하는 기능을 추가합니다.

useEffect(() => {
  if (searchKeyword && searchKeyword.length >= 1) {
    // 1. 검색어가 입력되었는지 확인
    const matchedPages = oddPagesData.filter((page) =>
      page.title.includes(searchKeyword)
    );

    // 2. 검색어와 일치하는 페이지가 있는지 확인
    if (matchedPages.length > 0) {
      const matchedPageIndex = oddPagesData.indexOf(matchedPages[0]) * 2;

      // 3. 현재 페이지 인덱스 업데이트
      setCurrentPageIndex(matchedPageIndex);

      // 4. 해당 페이지로 이동
      setTimeout(() => {
        pageFlipRef.current.pageFlip().flip(matchedPageIndex);
      }, 500);
    }
  }
}, [searchKeyword]);

 

위 코드에서 각 부분을 자세히 설명하겠습니다.

 

검색어가 입력되었는지 확인
if (searchKeyword && searchKeyword.length >= 1) {
  • 검색어가 비어있지 않고 길이가 1이상일 때만 코드를 실행함으로써 검색어가 입력되었는지 확인합니다.
검색어와 일치하는 페이지 찾기
const matchedPages = oddPagesData.filter((page) =>
  page.title.includes(searchKeyword)
);
  • oddPagesData 배열에서 각 페이지의 title 속성이 검색어를 포함하는지 필터링합니다. 일치하는 페이지들을 matchedPages 배열에 저장합니다.
  • 여기서 filter 메소드는 oddPagesData 배열을 순회하면서 각 page 객체의 title 속성이 searchKeyword를 포함하는지를 검사합니다.
일치하는 페이지가 있는지 확인
if (matchedPages.length > 0) {
  const matchedPageIndex = oddPagesData.indexOf(matchedPages[0]) * 2;
  • 일치하는 페이지가 하나 이상 있는 경우, 첫 번째 일치하는 페이지의 인덱스를 찾아 matchedPageIndex에 저장합니다. 이 인덱스는 해당 페이지의 짝수 인덱스를 나타내기 위해 2를 곱합니다.
  • oddPagesData.indexOf(matchedPages[0])는 일치하는 첫 번째 페이지의 인덱스를 반환합니다. 이 인덱스에 2를 곱하여 matchedPageIndex를 계산합니다.
  • 짝수 인덱스를 사용하는 이유는 페이지가 홀수 페이지와 짝수 페이지로 구성되어 있기 때문입니다.
현재 페이지 인덱스 업데이트
setCurrentPageIndex(matchedPageIndex);
  • 찾아낸 인덱스를 currentPageIndex 상태에 저장합니다.
해당 페이지로 이동
setTimeout(() => {
  pageFlipRef.current.pageFlip().flip(matchedPageIndex);
}, 500);
  • 0.5초 후에 PageFlip 컴포넌트의 flip 메소드를 호출하여 해당 페이지로 이동합니다.
  • setTimeout을 사용하는 이유는 페이지 이동이 부드럽게 이루어지도록 하기 위함입니다. 
  • pageFlipRef.current.pageFlip().flip(matchedPageIndex)는 PageFlip 컴포넌트의 flip 메소드를 호출하여 지정한 인덱스의 페이지로 이동합니다.

 

3. 전체 컴포넌트 연결

마지막으로, SnackSearch와 SnackList 컴포넌트를 포함한 상위 컴포넌트를 만들어서 연결합니다.

SnackInfoView.js
import React, { useState } from "react";
import styled from "styled-components";
import SnackSearch from "@/components/snackInfo/SnackSearch";
import SnackList from "@/components/snackInfo/SnackList";

// 기본적인 스타일링과 컴포넌트 정의
const SnackInfoViewBlock = styled.div``;

// SnackInfoView 컴포넌트 정의
const SnackInfoView = () => {
  const [searchKeyword, setSearchKeyword] = useState(""); // 검색어 상태

  const handleSearch = (keyword) => {
    setSearchKeyword(keyword); // 검색어 업데이트
  };

  return (
    <SnackInfoViewBlock>
      <SnackSearch onSearch={handleSearch} />
      <SnackList searchKeyword={searchKeyword} />
    </SnackInfoViewBlock>
  );
};

export default SnackInfoView;

SnackInfoView 컴포넌트는 SnackSearch 컴포넌트에서 검색어를 입력받아 searchKeyword 상태를 업데이트합니다. 

searchKeyword 상태가 변경되면 SnackList 컴포넌트에 전달하여 해당 페이지로 이동합니다.

 

이렇게 함으로써, 사용자는 검색어를 입력하여 책 형태의 네비게이션에서 원하는 페이지로 바로 이동할 수 있게 됩니다.