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

영화목록 (Netflix) 앱 8 - 영화 목록에서 특정 영화 삭제하기

syleemomo 2021. 11. 25. 19:34
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 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 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;
                        })
                        .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-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 파일을 위와 같이 수정하자!

 <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>

삭제 버튼 (X) 을 보여주기 위하여 div 요소를 추가한다. 또한, 해당 div 요소에 onClick 이벤트를 연결하여 삭제 버튼이 클릭되었을때 handleRemove 이벤트핸들러 함수가 실행될 수 있도록 한다. 이벤트핸들러 함수의 인자로 삭제할 영화의 id 값을 전달한다. 

최상위 div 요소로 감싸주고 key 속성을 Link 컴포넌트에서 최상의 div 요소로 이동하였다. 

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))

}

삭제버튼 (X) 이 클릭될때마다 실행되는 이벤트핸들러 함수이다. 삭제할 영화의 id 값을 가지고, 배열의 filter 함수로 삭제할 영화만 걸러낸다. 그런 다음 새로운 영화목록 (moviesFiltered) 으로 movies 상태를 업데이트해준다. 업데이트할때는 setMovies 함수를 사용한다. 

또한, 추천페이지에서는 좋아요 숫자를 바탕으로 추천 영화를 보여주기 때문에 만약 홈화면에서 삭제된 영화는 추천 페이지에 보이면 안된다. 그러므로 likes 정보를 조회하고, id 값을 이용하여 삭제할 영화의 좋아요 정보는 제거해준다. 이렇게 하면 해당 영화는 추천 페이지에 보이지 않게 된다. 

 

728x90