제로하우스

[React] 검색기능 구현하기 본문

React

[React] 검색기능 구현하기

송제로투 2022. 5. 9. 17:41

Overview

이번 글에서는 state와 eventListener 등을 사용하여 React에서 검색 기능을 구현해본다.
검색어를 입력하면 해당 검색어가 내용(tweet.content)에 포함된 더미 ​데이터(dummyTweets)가 표시되게 한다.
더미 데이터는 tweet의 사용자, 내용, 작성일자 등을 포함하고 있다.

결과 예시

 

준비하기


먼저 간단하게 골격을 만들어준다. Search라는 컴포넌트를 생성하고 검색창과 검색 결과 건수를 표시하는 텍스트, 그리고 결과를 표시할 공간을 만들어준다.

//Search.js

import React from 'react';
import { dummyTweets } from '../static/dummyData'; // duumy 데이터
import './Search.css'; // CSS 파일

class Search extends React.Component {
    render () {
        return (
            <div>
                {/* 검색창 */}
                <div className="searchBar_container">
                    <h3 className="searchBar_title">검색창</h3>
                    <input className="searchBar_input" type="search"></input>
                    <p className="searchBar_count"><small>검색결과: 건</small></p>
                </div>
                {/* 검색 결과 표시 */}
                <ul className="searchs">
                    결과 표시
                </ul>
            </div>
        );
    }
};

export default Search;

 

Step 1. 검색어 입력 받기


검색창에 키보드로 단어가 입력될 때 마다, 해당 값을 search()라는 함수로 보내어 처리하도록 한다.
이를 위해서 onKeyUp이라는 이벤트가 실행되는 경우, input 창의 값(value)를 가져와서 search 함수의 인자로 넘겨준다.

* onKeyUp 이벤트: 사용자가 키보드의 키를 눌렀다가 뗐을 때를 인식하는 이벤트이다.

{/* 검색창 */}
<div className="searchBar_container">
    <h3 className="searchBar_title">검색창</h3>
    {/* 검색어 가져오기 */}
    <input className="searchBar_input" type="search" onKeyUp={() => {
        var word = document.querySelector('.searchBar_input').value
        this.search(word)
    }}></input>
    <p className="searchBar_count"><small>검색결과: {this.state.filteredTweets.length}건</small></p>
</div>

 

Step 2. 검색어 포함 여부 체크하기


search함수는 입력된 검색어 문자열이 tweet 데이터 내용에 포함되어 있는지를 체크해주는 함수이다.
search 함수를 선언해준다. 필터된 결과 값은 filterTweets라는 함수의 인자로 보내준다. 그리고 빈 검색어가 입력된 경우에는 포함 여부를 체크할 필요가 없으므로, if문으로 케이스를 나누어준다.

// tweet 내용에 검색어가 포함되는지 체크하고 필터링하는 함수
search (word) {
    if (word !== '') {
        var result = dummyTweets.filter(tweet => tweet.content.includes(word))
        this.filterTweets(result)
    }
    else {
        this.filterTweets([])
    }
}

 

Step 3. 필터링된 데이터 저장하기


검색어가 포함된 데이터를 별도로 state에 저장해준다. 이 데이터는 변경이 있을 때마다 확인을 해주어야 하기 때문에 state를 사용한다.
filterTweets 함수는 이 state의 데이터를 변경해주기 위한 함수로, setState() 메서드로 필터링된 데이터가 변경이 있을 때마다 저장될 수 있도록 한다.

// 필터링된 데이터를 state에 저장
state = {
    filteredTweets: [],
};
// 필터링된 데이터를 별도로 저장하는 함수
filterTweets (result) {
    this.setState(() => {
        return {filteredTweets: result}
    })
}

 

Step 4. 필터링된 데이터 보여주기


마지막으로 state에 저장한 필터링 데이터(filteredTweets)를 결과 표시 공간에 보여준다.
array의 map method를 사용하여 적절하게 결과를 표시해준다.

{/* 검색 결과 표시 */}
<ul className="searchs">
    {this.state.filteredTweets.map((tweet) => {
    return (
        <li className="search" key={tweet.id}>
            <div className="search__profile">
            <img src={tweet.picture} />
            </div>
            <div className="search__content">
            <div className="search__userInfo">
                <span className="search__username">{tweet.username}</span>
                <span className="search__createdAt">{tweet.createdAt}</span>
            </div>
            <div className="search__message">{tweet.content}</div>
            </div>
        </li>
        )
    })}
</ul>

 

Step 5. 검색 결과 개수 표시하기


length를 사용하여 간단하게 검색 결과 개수를 표시해준다.

 {/* 검색창 */}
 <div className="searchBar_container">
    <h3 className="searchBar_title">검색창</h3>
    <input className="searchBar_input" type="search" onKeyUp={() => {
        var word = document.querySelector('.searchBar_input').value
        this.search(word)
    }}></input>
    {/* 검색 결과 개수 표시 */}
    <p className="searchBar_count"><small>검색결과: {this.state.filteredTweets.length}건</small></p>
</div>

 

 

전체 코드 보기

import React from 'react';
import { dummyTweets } from '../static/dummyData'; // duumy 데이터
import './Search.css'; // CSS 파일

class Search extends React.Component {
    // 필터링된 데이터를 state에 저장
    state = {
        filteredTweets: [],
    };
    // 필터링된 데이터를 별도로 저장하는 함수
    filterTweets (result) {
        this.setState(() => {
            return {filteredTweets: result}
        })
    }
    // tweet 내용에 검색어가 포함되는지 체크하고 필터링하는 함수
    search (word) {
        if (word !== '') {
            var result = dummyTweets.filter(tweet => tweet.content.includes(word))
            this.filterTweets(result)
        }
        else {
            this.filterTweets([])
        }
    }
    render () {
        return (
            <div>
                 {/* 검색창 */}
                 <div className="searchBar_container">
                    <h3 className="searchBar_title">검색창</h3>
                    <input className="searchBar_input" type="search" onKeyUp={() => {
                        var word = document.querySelector('.searchBar_input').value
                        this.search(word)
                    }}></input>
                    {/* 검색 결과 개수 표시 */}
                    <p className="searchBar_count"><small>검색결과: {this.state.filteredTweets.length}건</small></p>
                </div>
                {/* 검색 결과 표시 */}
                <ul className="searchs">
                    {this.state.filteredTweets.map((tweet) => {
                    return (
                        <li className="search" key={tweet.id}>
                            <div className="search__profile">
                            <img src={tweet.picture} />
                            </div>
                            <div className="search__content">
                            <div className="search__userInfo">
                                <span className="search__username">{tweet.username}</span>
                                <span className="search__createdAt">{tweet.createdAt}</span>
                            </div>
                            <div className="search__message">{tweet.content}</div>
                            </div>
                        </li>
                        )
                    })}
                </ul>
            </div>
        );
    }
};


export default Search;

'React' 카테고리의 다른 글

[TIL][React] 06 Event  (0) 2022.05.13
[TIL][React] 05 Data (props & state)  (0) 2022.05.13
[TIL][React] 04 Router  (0) 2022.05.09
[TIL][React] 03 SPA(Single Page Application)  (0) 2022.05.09
[TIL][React] 02 JSX(JavaScript XML)  (0) 2022.05.09
Comments