프로젝트/영화 목록 (Netflix) 앱

영화목록 (Netflix) 앱 9 - 홈화면에 영화목록 전체보기 기능 만들기

syleemomo 2021. 11. 25. 20:00
728x90

 

* 영화목록 전체보기 기능 구현하기

import React, { useState, useEffect } from 'react'
import { Link, useNavigate } from 'react-router-dom'

import { Movie, Loading, Input, Button, Menu } from 'components'
import './Home.css'

const Home = () => {
    const [loading, setLoading] = useState(true)
    const [movies, setMovies] = useState([])
    const [query, setQuery] = useState('')
    const [isSorted, setIsSorted] = useState(-1)
    const [limit, setLimit] = useState(6)
    const navigate = useNavigate()

    const likes = JSON.parse(sessionStorage.getItem('likes')) || {}
    console.log(likes)
    

    useEffect( () => {
        fetch('https://yts.mx/api/v2/list_movies.json?limit=20')
        .then( res => res.json())
        .then( result => {
            const {data: {movies}} = result
            console.log(movies)
            setLoading(false)
            setMovies(movies)
        })
    }, [])

    const handleChange = (e) => {
        const { value } = e.target
        setQuery(value)
    }

    const sortByYear = (e) => {
        setIsSorted(isSorted * -1)
    }

    const updateLikes = (id) => {
        const likes = JSON.parse(sessionStorage.getItem('likes')) || {}
       
        if(likes[id] === null || likes[id] === undefined){
            likes[id] = 0
        }
        likes[id] += 1
        sessionStorage.setItem('likes', JSON.stringify(likes))
    }

    const handleRemove = (id) => {
        const moviesFiltered = movies.filter(movie => movie.id !== id)
        setMovies(moviesFiltered)

        // likes 리스트에서도 해당 영화에 대한 좋아요 정보 제거
        const likes = JSON.parse(sessionStorage.getItem('likes')) || {}
        delete likes[id]
        sessionStorage.setItem('likes', JSON.stringify(likes))

    }
    const displayEntireMovies = () => {
        console.log('display all movies !')
        setLimit(movies.length)
    }

    const homeUI = movies
                        .filter(movie => {
                            const title = movie.title.toLowerCase()
                            const genres = movie.genres.join(' ').toLowerCase()
                            const q = query.toLowerCase()
                        
                            return title.includes(q) || genres.includes(q)
                        })
                        .sort( (a, b) => {
                            return (b.year - a.year) * isSorted;
                        })
                        .slice(0, limit)
                        .map(movie =>
                            <div className='movie-item' key={movie.id}  >
                                <div className='movie-delete' onClick={(e) => handleRemove(movie.id)}>X</div>
                                <Link 
                                    to='/detail'
                                    state={{ movie }} 
                                    style={{ textDecoration: 'none', color: 'white'}}
                                    onClick={() => updateLikes(movie.id)}
                                >
                                    
                                    <Movie 
                                            title={movie.title} 
                                            genres={movie.genres} 
                                            cover={movie.medium_cover_image} 
                                            summary={movie.summary}
                                            year={movie.year}
                                            rating={movie.rating}
                                            likes={likes[movie.id]}
                                        />
                                </Link>
                            </div> 
                                    )

    const toRankPage = () => {
        navigate('/recommend', { state: { movies }})
    }
    return (
        <>
            {loading? <Loading/>: <div className='Home-container'>
                                    <Menu>
                                        <Button handleClick={toRankPage}>Rank</Button>
                                    </Menu>
                                    <div className='Home-entire'>
                                        <Button handleClick={displayEntireMovies}>See Entire Movies</Button>
                                    </div>
                                    
                                    <div className='Home-contents'>
                                        <Input name='search' type='text' placeholder='Search movies ...' value={query} onChange={handleChange}/>
                                        <Button handleClick={sortByYear}>정렬</Button>
                                        <div className='Home-movies'>{homeUI}</div>
                                    </div>
                                  </div>}
        </>
    )
}

export default Home

Home.js 파일을 위와 같이 수정하자!

const [limit, setLimit] = useState(6)

리액트 훅을 이용하여 처음 홈화면이 나타날때 보여줄 영화의 갯수를 설정한다. 처음 홈화면이 렌더링할때 6개의 영화목록만 보여주도록 한다. 

movies
    .filter(movie => {
        const title = movie.title.toLowerCase()
        const genres = movie.genres.join(' ').toLowerCase()
        const q = query.toLowerCase()

        return title.includes(q) || genres.includes(q)
    })
    .sort( (a, b) => {
        return (b.year - a.year) * isSorted;
    })
    .slice(0, limit)

limit 값에 따라 보여줄 영화 갯수를 조절할 수 있도록 배열의 slice 메서드를 사용하여 설정한다. 

<div className='Home-entire'>
    <Button handleClick={displayEntireMovies}>See Entire Movies</Button>
</div>

버튼을 클릭하면 전체 영화목록을 보여줄 수 있도록 displayEntireMovies 라는 이벤트핸들러 함수를 연결한다. 

const displayEntireMovies = () => {
    console.log('display all movies !')
    setLimit(movies.length)
}

이벤트핸들러 함수가 실행되면 movies.length 라는 전체 영화 갯수로 limit 값을 업데이트해준다. 

 

* 영화목록 전체보기 버튼 스타일링하기

.Home-container{
    background: url('../assets/images/background.jpg');
    width: 100%;
    padding: 30px;
    text-align: center;
    border: 1px solid black;
    position: relative;
}
.Home-contents{
    /* border: 5px solid orange; */
    margin-top: 100px;
}
.Home-movies{
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    align-items: center;
    width: 60%;
    margin: 0px auto;
    text-align: center;
}
.movie-item{
    position: relative;
}
.movie-delete{
    width: 50px;
    height: 50px;
    color: black;
    background: transparent;
    opacity: 0.6;
    position: absolute;
    cursor: pointer;
    top: 10px;
    right: 10px;
    z-index: 1;
    text-align: center;
    line-height: 50px;
    font-weight: bold;
    font-size: 1.5rem;
}
.movie-delete:hover{
    background: #a9a9a9;
}
.Home-entire{
    position: fixed;
    right: 10px;
    bottom: 10px;
}

Home.css 파일을 위와 같이 수정하자!

728x90