1. 검색창 구현

검색값을 useState(훅)을 이용해서 관리한다.

입력창에 이벤트 핸들러 onChange를 사용하여 변경이 발생할 경우(가령 글자를 칠 경우) 그 값을 searchTerm에 업데이트 진행.

searchTerm을 기준으로 필터링하여 blog 배열을 다시 정의 후 화면 다시 렌더링.

// BlogGrid.js
import React, { useState, useEffect } from 'react';
import '../styles.css';
import BlogCard from './BlogCard';


export default function BlogGrid() {

    // 상태를 업데이트 한다
    const [blogs, setBlogs] = useState([]);

    // 검색용
    const [searchTerm, setSearchTerm] = useState("");

    const handleSearchChange = (e) => {
        // 입력창의 값을 searchTerm 변수에 실시간 업데이트 진행
        setSearchTerm(e.target.value)
    }

    const filteredBlogs = blogs.filter(blog =>
        blog.title.toLowerCase().includes(searchTerm.toLowerCase())
    )
    // fetch로 데이터를 가져온 후 json으로 변환 후 blogs 배열을 업데이트 한다. 
    useEffect(() => {
        fetch("blog.json")
            .then(response => response.json())
            .then(data => setBlogs(data))

    }, [])

    return (
        <div>
            <input type="text"
                className='search-input'
                placeholder="Search Blogs..."
                value={searchTerm}
                onChange={handleSearchChange}
            />
            <div className='blogs-grid'>
                {
                    filteredBlogs.map(blog => (
                        <BlogCard blog={blog} key={blog.id}></BlogCard>
                    ))
                }
            </div>
        </div>
    )
}

 

2. 기타

(1) 이벤트 핸들러 onError 을 이용하여 이미지가 없을 경우 예외처리 진행

(2) 조건에 따라 적용할 className 바꾸기

점수가 어느 구간에 속하느냐에 따라 다른 className 적용하기(백틱 사용 유의)

// BlogCard.js
import React from "react";
import "../styles.css"

// 이미지를 못 불러올 경우 예외 처리
const handleError = (e) => {
    e.target.src = "images/default.jpg"
}

// 평점에 따른 UI 변경
const getScoreClass = (score) => {
    if (score > 8) return "score-good"
    if (score >= 5 && score < 8) return "score-ok"
    if (score < 5) return "score-bad"

}
export default function BlogCard({ blog }) {

    return (
        <div key={blog.id} className='blog-card'>
            <img src={blog.image} alt={blog.title} onError={handleError} />
            <div className='blog-card-info'>
                <h3 className='blog-card-title'>{blog.title}</h3>
                <p className='blog-card-mood'>{blog.date}</p>
                <p className='blog-card-mood'>{blog.mood}</p>
                <p className={`blog-card-score ${getScoreClass(blog.score)}`}>{blog.score}</p>
            </div>
        </div>
    )

}

 

3. 결과

아래 화면에서 lo라고 검색할 경우 실시간으로 일치하는 검색결과만 나온다.

[참고] Develop React JS web applications including components, state, effect, hooks, React router, reducer, context, etc.

+ Recent posts