리액트 검색 기능 구현하기

피시본·2023년 3월 4일
0

PROJECT에서 살아남기

목록 보기
10/10

검색 기능 구현하기

3차 프로젝트에서 구현하지 못했던 검색 기능을 이번에 구현했다.
그래도 . . . 조금은 성장한 걸까 . . . ? 기쁘다 😊 😊 😊 오늘의 코드도 미래에 보면 웃기겠지? 그러길 바라는 마음으로 기록한다.

한 가지 고민인 건 검색 기능이 서비스 이곳저곳에 들어가 있어 hook으로 빼서 활용하면 좋을 것 같은데 . . . 일단 기능 구현부터 해봤다. 나중에 hook으로 빼는 걸 성공한다면 그때 또 기록할 예정이다.


오늘 할 것은 커뮤니티 목록에서 커뮤니티 이름과 소개글로 검색하는 기능이다. 백엔드에서 검색어를 넣으면 DB에서 꺼내주는 API까지는 짜주셨다. 그걸 한 공간에 띄우는 것이 내 할일!

1. 검색어 변수 및 onChange 함수 선언

먼저 input에 넣을 검색어를 정의해줬다.
그리고 onChange로 바뀌는 값을 감지하게 해준다.

const [userInput, setUserInput] = useState<string>('');

const getSearchData = (e: ChangeEvent<HTMLInputElement>) => {
  setUserInput(e.target.value.toLowerCase());
  }
... 
return 
	<input onChange={getSearchData} type="text" 
    placeholder="커뮤니티 이름 또는 소개글로 검색됩니다" />

2. 검색 목록 넣을 상자 선언

서치가 끝나면 나올 목록 리스트를 담는 상자가 필요하다.
만들어뒀던 커뮤니티 타입을 타입으로 지정한다.

const [searchLists, setSearchLists] = useState<CommunityType[]>([]);

3. 검색 함수 선언 및 버튼 연결

검색 버튼을 누르면 검색해줄 함수가 필요하다.
함수 안에서 백엔이 주는 정보를 가져와 위에 정의한 리스트에 담아준다. 그리고 검색 버튼에 연결한다.

const onClickSearchInput = async (e: React.MouseEvent) => {
    e.preventDefault();
    const res = await getSearchRequest(userInput);
    // getSearchRequest는 백엔에서 준 API를 받아오는 함수를 따로
    // 함수로 정의했고 거기서 꺼내옴
    setSearchLists(res.rows);
  };

<button
	onClick={onClickSearchInput}
    disabled={userInput.length === 0}
    // 인풋값이 없으면 검색 버튼이 작동하지 않도록 설정했다.
> 검색 
</button>

함수 안 setSearchLists에 값을 넣기 전에 콘솔에 먼저 찍어 보면 원하는 값이 나올 것이다. 이제 이걸! map을 이용해 원하는 곳에 띄워주면 된다.

여기서 정말 많은 시간을 잡아 먹었다.
커뮤니티 목록을 띄워주는 곳에서 검색 결과 목록도 띄워줘야 하므로 두 상황을 나눠줄 조건이 필요하다. 문제를 해결한 지금은 바로 불리언 값으로 나눠주면 되겠구나! 생각하지만 . . . 한 번에 생각 못 하고 이것저것 시도를 엄청 해봤다.

3-1. 시도1

{ searchLists.length === 0 ?
	커뮤니티 전체 목록 ~
    :
    서치 목록
}

검색어가 없으면 전체 목록이 뜬다. 그러나 당연하게도 검색 결과가 없어도 전체 목록이 떠버린다. 검색 결과가 없으면 searchLists가 0이기에 . . . 그래서 생각한 방법 . . . '검색 결과가 없을 때 인풋에 글자가 남아 있으니 글자 수로 나누면 되지 않을까 ...?'

3-2. 시도2

{searchLists.length === 0 ?
	{userInput.length > 0 ? (
    	<div>검색 결과가 없습니다.</div>
        :
        ...
        커뮤니티 전체 목록 ~

이러면 커뮤니티 목록도 잘 뜨고 검색 결과가 있어도 없어도 다 잘 뜨지만 한 가지 문제가 있다면 인풋에 넣는 글자 값이 onChange로 시시각각 변하기에 검색 결과가 없을 때 뜨는 문구가 그대로 노출이 된다는 것.

지금 생각해보면 되게 어처구니 없지만 저걸 구현할 때는 일단 잘못된 걸 알긴 아는데 이것저것 구현해보는 게 최우선이라고 생각해서 아무렇게나 막 망쳐봤다 ㅋㅋㅋㅋㅋ
가만히 앉아서 문제를 어떻게 해결할까 고민하다가 문득 기고 아니고의 조건을 달아주면 되잖아? 불리언 값으로 나누면 되잖아!!!!!! 유레카를 외친 아르키메데스의 심정을 알 것 같았다.

자... 한 번 해보자.

4. 띄워줄 목록 나누는 조건 정의

조건을 불리언 값으로 정의한다.

const [isSearching, setIsSearching] = useState<boolean>(false);

const onClickSearchInput = async (e: React.MouseEvent) => {
    e.preventDefault();
    const res = await getSearchRequest(userInput);
    setSearchLists(res.rows);
    setIsSearching(true); <- new!
  };
  
return 
{!isSearching ? (
	전체 목록 띄워주는 부분)
    :
    {searchLists.length === 0 ? (
   	  <span>검색 결과가 없습니다.</span>
    ) : (
      <div>
        {searchLists.map((item) => (
          <CommuListCard listInfo={item} />
        ))}
      </div>
      ...

이걸 왜 생각 못 했을까!!!!! 하지만 이렇게 성장하는 거겠지!!!!! 정말 기뻤다!!!!!!!
그러나 한 가지 문제가 또 있었다.

😭😭😭 검색어를 지우면 전체 목록이 뜨게 하고 싶은데 안 뜨잖아..!!!! 😭😭😭
무한 콘솔 콘솔 콘솔 콘솔 ... 콘솔로그가 있어 참말로 다행이었다. 콘솔로그로 잔머리를 굴렸으니 . . .

어라..? 인풋창을 비웠는데 userInput.length가 1로 남네...?
그리고 이 빈 칸에서 무언가를 쳐야 => length === 0이 된다. 오케이 조건을 주자. onChange 함수에 조건을 주자.

5. 검색어 없을 때 전체 목록 띄우기

const getSearchData = (e: ChangeEvent<HTMLInputElement>) => {
	setUserInput(e.target.value.toLowerCase());
    
    if (userInput.length <= 1) {
    	setIsSearching(false);
    } <- new!
}

으아아아아아ㅏㅏㅏㅏ 드디어 ... 원하는 대로 기능이 된다 ...! ! ! ! !
이해한 대로 프로세스를 짜 넣었는데 무언가 얼레벌레 ...~ 하다. 좀 더 깔끔하게 코드를 칠 방법이 있을 것 같다. 생각나면 시도해보려고 한다. 일단 지금의 나로서는 이게 최선! 기쁘다! 😚😚😆

profile
Hello, World!

0개의 댓글