Firebase 제목으로 게시글을 검색하자..

준영·2023년 9월 2일
0

Firebase를 써보자..

목록 보기
8/8

Firebase 제목으로 게시글을 검색하자..

구상하기

  1. 검색할 인풋창을 만들어주고,
  2. 검색어를 useState로 선언하고 onChange이벤트로 입력값을 setState로 업데이트 해준다.
  3. 검색어가 없을 시, !searchKeyword && 기존에 보여줬던 게시글 리스트를 보여준다.
    • 입력받은 검색어로 새로운 검색 결과 리스트를 반환하는 로직이 실행된다. +디바운스 필수
  4. 검색어가 있을 시, searchKeyword && 기존에 보여주던 게시글 리스트는 보여주지 않고 검색어에 맞게 나온 리스트를 보여준다.

사용예제

CustomHook

menu라는 string 타입의 값은 페이지 진입 시, 어느 게시판 테이블의 데이터를 가져오거나 검색을 하는지를 알 수 있는 값이다.

그리고 디바운스를 사용함으로 어느정도의 최적화도 고려해주었다.

export const useBoardSearch = (menu: string) => {
    const [searchKeyword, setSearchKeyword] = useState("");
    const [searchResult, setSearchResult] = useState<DocumentData[]>([]);

    useEffect(() => {
        const searchBoardFunc = _.debounce(async () => {
            const q = query(
                collection(firebaseDb, menu), // 포스트 컬렉션
                orderBy("title"), // 제목 정렬
                startAt(searchKeyword),
                endAt(searchKeyword + "\uf8ff")
            );
            const resSnap = await getDocs(q);
            const searchData = resSnap.docs.map((doc) => doc.data());
            setSearchResult(searchData);
        }, 1000);
        searchBoardFunc();
    }, [searchKeyword]);

    return [searchKeyword, setSearchKeyword, searchResult] as const;
};

Board.tsx (가독성을 위해 생략)

export default function Board(props: { menu: string }) {
    // search board
    const [searchKeyword, setSearchKeyword, searchResult] =
        useBoardSearch(menu);

    return (
        <Boards.Wrapper>
            <div style={{ position: "relative" }}>
                <SearchBoardInput setSearchKeyword={setSearchKeyword} />
            </div>
              
                <Boards.BoardListBox>
                    {!searchKeyword &&
                        boardData.map((el, index) => (
                            <Boards.Board
                                key={index}
                                id={el.id}
                                onClick={moveToDetail}
                                isDark={darkMode}
                            >
                                <Boards.BoardNumber>
                                    {boardListData.length -
                                        (page - 1) * limit -
                                        index}
                                </Boards.BoardNumber>
                                <Boards.BoardTitle>
                                    {el.title}
                                </Boards.BoardTitle>
                                <Boards.Name>{el.name}</Boards.Name>
                                <Boards.BoardDate>
                                    {
                                        el.timestamp
                                            .toDate()
                                            .toISOString()
                                            .split("T")[0]
                                    }
                                </Boards.BoardDate>
                            </Boards.Board>
                        ))}

                    {searchKeyword &&
                        searchResult.map((el, index) => (
                            <Boards.Board
                                key={index}
                                id={el.id}
                                onClick={moveToDetail}
                                isDark={darkMode}
                            >
                                <Boards.BoardNumber>
                                    {searchResult.length - index}
                                </Boards.BoardNumber>
                                <Boards.BoardTitle>
                                    {el.title}
                                </Boards.BoardTitle>
                                <Boards.Name>{el.name}</Boards.Name>
                                <Boards.BoardDate>
                                    {
                                        el.timestamp
                                            .toDate()
                                            .toISOString()
                                            .split("T")[0]
                                    }
                                </Boards.BoardDate>
                            </Boards.Board>
                        ))}
                </Boards.BoardListBox>
            </div>
        </Boards.Wrapper>
    );
}

결과

profile
개인 이력, 포폴 관리 및 기술 블로그 사이트 👉 https://aimzero-web.vercel.app/

0개의 댓글