찾다
웹 프론트엔드CSS 튜토리얼React를 사용하여 Movie Finder 웹사이트 구축하기

Building a Movie Finder Website using React

소개

이번 블로그에서는 React와 OMDB API를 사용하여 Movie Finder 웹사이트를 구축하는 과정을 살펴보겠습니다. 이 웹사이트를 통해 사용자는 어벤져스, 스타워즈, 시리즈 등의 카테고리별로 영화를 탐색하고 특정 검색어를 사용하여 영화를 검색할 수 있습니다. 각 영화에는 세부 정보 페이지가 있어 좋아하는 영화에 대해 더 쉽게 탐색할 수 있습니다.

프로젝트 개요

Movie Finder 웹사이트를 통해 사용자는 다음을 수행할 수 있습니다.

  • 어벤져스, 스타워즈 등의 카테고리를 찾아보세요.
  • 키워드로 영화를 검색하세요.
  • 영화 상세 정보(포스터, 장르, 감독, 배우 등)를 확인하세요.
  • 깔끔하고 모던한 디자인으로 웹사이트를 쉽게 탐색하세요.

특징

  • OMDB API를 사용하여 동적으로 데이터를 가져옵니다.
  • 더 나은 사용자 경험을 위한 반응형 디자인
  • 즉시 결과를 제공하는 검색 기능
  • 데이터를 가져오는 동안 표시기를 로드합니다.
  • 별도의 페이지에서 개별 영화의 세부정보를 확인하세요.

사용된 기술

  • React: UI 구성요소 구축을 위한 프런트엔드 라이브러리
  • React Router: 탐색 및 라우팅용.
  • Axios: OMDB API에 대한 HTTP 요청용.
  • OMDB API: 영화 세부정보를 가져옵니다.
  • CSS: 애플리케이션 스타일을 지정합니다.

프로젝트 구조

프로젝트의 디렉토리 구조는 다음과 같습니다.

movie-finder/
├── public/
├── src/
│   ├── components/
│   │   └── Navbar.js
│   │   └── Footer.js
│   ├── pages/
│   │   └── Home.js
│   │   └── Movies.js
│   │   └── Series.js
│   │   └── SearchResults.js
│   │   └── MovieDetail.js
│   └── App.js
│   └── App.css
└── package.json

설치

  1. 저장소 복제:

    git clone https://github.com/abhishekgurjar-in/movie-finder.git
    cd movie-finder
    
  2. 종속성 설치:

    npm install
    
  3. OMDB API에서 API 키를 받으세요.

  4. 프로젝트 루트에 .env 파일을 생성하고 API 키를 추가하세요.

    REACT_APP_OMDB_API_KEY=yourapikey
    
  5. 프로젝트 실행:

    npm start
    

용법

1. 홈페이지

홈페이지에서는 어벤져스와 스타워즈라는 두 가지 카테고리의 영화를 선보입니다. 사용자가 영화 카드를 클릭하면 영화 상세 페이지로 리디렉션됩니다.

Home.js의 코드 조각:

import React, { useEffect, useState } from "react";
import axios from "axios";
import { useNavigate } from "react-router-dom";
import Movies from "./Movies";
import Series from "./Series";

const Home = () => {
  const [avengersMovies, setAvengersMovies] = useState([]);
  const [starWarsMovies, setStarWarsMovies] = useState([]);
  const [loadingAvengers, setLoadingAvengers] = useState(true);
  const [loadingStarWars, setLoadingStarWars] = useState(true);
  const navigate = useNavigate();

  useEffect(() => {
    fetchMovies("Avengers", setAvengersMovies, setLoadingAvengers);
    fetchMovies("Star Wars", setStarWarsMovies, setLoadingStarWars);
  }, []);

  const fetchMovies = (query, setMovies, setLoading) => {
    axios
      .get(`http://www.omdbapi.com/?s=${query}&apikey=you_api_key`)
      .then((response) => {
        if (response.data.Search) {
          setMovies(response.data.Search);
        } else {
          setMovies([]); // Clear movies if no results
        }
      })
      .catch((error) => {
        console.error(`There was an error fetching the ${query} movies!`, error);
        setMovies([]); // Clear movies if there is an error
      })
      .finally(() => {
        setLoading(false);
      });
  };

  const handleCardClick = (id) => {
    navigate(`/movie/${id}`);
  };

  const renderMovies = (movies, loading) => (
    loading ? (
      <div classname="loader"><div classname="load"></div></div>
    ) : (
      <div classname="cards">
        {movies.length > 0 ? (
          movies.map((movie) => (
            <div key="{movie.imdbID}" classname="card" onclick="{()"> handleCardClick(movie.imdbID)}>
              <img src="%7Bmovie.Poster%7D" alt="{movie.Title}">
              <h2 id="movie-Title">{movie.Title}</h2>
            </div>
          ))
        ) : (
          <p>No movies found.</p>
        )}
      </div>
    )
  );

  return (
    
      <div classname="home">
        <div classname="movie-category">
          <h4 id="Avengers-Movies">Avengers Movies</h4>
          {renderMovies(avengersMovies, loadingAvengers)}
        </div>
        <br>
        <br>
        <div classname="movie-category">
          <h4 id="Star-Wars-Movies">Star Wars Movies</h4>
          {renderMovies(starWarsMovies, loadingStarWars)}
        </div>
      </div>
      <movies></movies>
      <series></series>
    >
  );
};

export default Home;

2. 검색 기능

사용자는 웹사이트 상단의 검색창을 사용하여 모든 영화를 검색할 수 있습니다. 사용자의 쿼리를 기반으로 OMDB API에서 검색 결과를 가져옵니다.

SearchResults.js의 코드 조각:

import React, { useEffect, useState } from "react";
import axios from "axios";
import { useParams, useNavigate } from "react-router-dom";

const SearchResults = () => {
  const [movies, setMovies] = useState([]);
  const [loading, setLoading] = useState(false);
  const { query } = useParams();
  const navigate = useNavigate(); // Add this line to use navigate

  useEffect(() => {
    if (query) {
      setLoading(true);  // Set loading to true before starting the fetch
      axios
        .get(`http://www.omdbapi.com/?s=${query}&apikey=your_api_key`)
        .then((response) => {
          if (response.data.Search) {
            setMovies(response.data.Search);
          } else {
            setMovies([]); // Clear movies if no results
          }
        })
        .catch((error) => {
          console.error("There was an error fetching the movie data!", error);
        })
        .finally(() => {
          setLoading(false);  // Set loading to false once fetch is complete
        });
    }
  }, [query]);

  const handleCardClick = (id) => {
    navigate(`/movie/${id}`); // Navigate to movie detail page
  };

  return (
    <div classname="search-results">
      <h4 id="Search-Results-for-query">Search Results for "{query}"</h4>
      {loading ? (
        <div classname="loader"><div classname="load"></div></div>  // Loader
      ) : (
        <div classname="cards">
          {movies.length > 0 ? (
            movies.map((movie) => (
              <div key="{movie.imdbID}" classname="card" onclick="{()"> handleCardClick(movie.imdbID)}>
                <img src="%7Bmovie.Poster%7D" alt="{movie.Title}">
                <h2 id="movie-Title">{movie.Title}</h2>
              </div>
            ))
          ) : (
            <p>No results found.</p>
          )}
        </div>
      )}
    </div>
  );
};

export default SearchResults;

3. 영화 상세페이지

사용자가 영화를 클릭하면 영화 세부정보 페이지로 리디렉션됩니다. 이 페이지에는 영화 제목, 포스터, 줄거리, 배우 등이 표시됩니다.

MovieDetail.js의 코드 조각:

import React, { useEffect, useState } from 'react';
import axios from 'axios';
import { useParams } from 'react-router-dom';

const MovieDetail = () => {
  const [movie, setMovie] = useState(null);
  const [loading, setLoading] = useState(true);
  const { id } = useParams();

  useEffect(() => {
    axios.get(`http://www.omdbapi.com/?i=${id}&apikey=your_api_key`)
      .then((response) => {
        setMovie(response.data);
      })
      .catch((error) => {
        console.error("There was an error fetching the movie details!", error);
      })
      .finally(() => {
        setLoading(false);
      });
  }, [id]);

  if (loading) return <div classname="loader">
    <div classname="load"></div>
  </div>;
  if (!movie) return <div classname="loader">No movie data found!</div>;

  return (
    <div classname="movie-detail">

<div classname="detail-box">
<h1 id="movie-Title">{movie.Title}</h1>
<p><strong>Year:</strong> {movie.Year}</p>
      <p><strong>Rating:</strong> {movie.imdbRating}</p>
      <p><strong>Genre:</strong> {movie.Genre}</p>
      <p><strong>Director:</strong> {movie.Director}</p>
      <p><strong>Actors:</strong> {movie.Actors}</p>
      <p><strong>Plot:</strong> {movie.Plot}</p>
      <p><strong>Runtime:</strong> {movie.Runtime}</p>
      <p><strong>Language:</strong> {movie.Language}</p>
      <p><strong>Country:</strong> {movie.Country}</p>
      <p><strong>Awards:</strong> {movie.Awards}</p>
</div>
    <div classname="img-box">
    <img src="%7Bmovie.Poster%7D" alt="{movie.Title}">
    </div>
    </div>
  );
};

export default MovieDetail;

4. 영화 및 시리즈 페이지

Movies.jsSeries.js 페이지에는 각각 영화와 TV 시리즈가 나열됩니다.

Movies.js의 코드 조각:

import React, { useEffect, useState } from "react";
import axios from "axios";
import { useNavigate } from "react-router-dom";

const Movies = () => {
  const [movies, setMovies] = useState([]);
  const navigate = useNavigate();

  useEffect(() => {
    axios
      .get(`http://www.omdbapi.com/?s=Avengers&type=movie&apikey=${process.env.REACT_APP_OMDB_API_KEY}`)
      .then(response => setMovies(response.data.Search || []))
      .catch(error => console.error(error));
  }, []);

  const handleCardClick = (id) => {
    navigate(`/detail/${id}`);
  };

  return (
    <div classname="movies">
      <h2 id="Movies">Movies</h2>
      <div classname="cards">
        {movies.map(movie => (
          <div key="{movie.imdbID}" classname="card" onclick="{()"> handleCardClick(movie.imdbID)}>
            <img src="%7Bmovie.Poster%7D" alt="{movie.Title}">
            <h3 id="movie-Title">{movie.Title}</h3>
          </div>
        ))}
      </div>
    </div>
  );
};

export default Movies;

Series.js의 코드 조각:

import React, { useEffect, useState } from "react";
import axios from "axios";
import { useNavigate } from "react-router-dom";

const Series = () => {
  const [series, setSeries] = useState([]);
  const navigate = useNavigate();

  useEffect(() => {
    axios
      .get(`http://www.omdbapi.com/?s=Star Wars&type=series&apikey=${process.env.REACT_APP_OMDB_API_KEY}`)
      .then(response => setSeries(response.data.Search || []))
      .catch(error => console.error(error));
  }, []);

  const handleCardClick = (id) => {
    navigate(`/detail/${id}`);
  };

  return (
    <div classname="series">
      <h2 id="TV-Series">TV Series</h2>
      <div classname="cards">
        {series.map(show => (
          <div key="{show.imdbID}" classname="card" onclick="{()"> handleCardClick(show.imdbID)}>
            <img src="%7Bshow.Poster%7D" alt="{show.Title}">
            <h3 id="show-Title">{show.Title}</h3>
          </div>
        ))}
      </div>
    </div>
  );
};

export default Series;

5. Navbar 구성 요소

Navbar 구성요소를 사용하면 사용자가 여러 페이지 사이를 탐색하고 검색을 수행할 수 있습니다.

Navbar.js가 업데이트되었습니다.

import React, { useState } from "react";
import { NavLink, Link } from "react-router-dom";

const Navbar = () => {
  const [searchQuery, setSearchQuery] = useState("");

  const handleSearch = (event) => {
    if (event.key === 'Enter' && searchQuery.trim()) {
      document.getElementById('search-link').click();
    }
  };

  return (
    <div classname="navbar">
      <div classname="logo">
        <h1 id="Movie-Finder">Movie Finder</h1>
      </div>

      <div classname="page-list">
        <navlink to="/">
          <h4 id="Home">Home</h4>
        </navlink>
        <navlink to="/movies">
          <h4 id="Movies">Movies</h4>
        </navlink>
        <navlink to="/series">
          <h4 id="TV-Series">TV Series</h4>
        </navlink>
      </div>
      <div classname="search-box">
        <input type="text" placeholder="Search for movies or series" value="{searchQuery}" onchange="{(e)"> setSearchQuery(e.target.value)}
          onKeyDown={handleSearch}
        />
        <link to="{`/search/${searchQuery}`}" id="search-link">
          <button>Search</button>
        
      </div>
    </div>
  );
};

export default Navbar;

6. 바닥글 구성요소

바닥글 구성요소는 간단한 바닥글 메시지를 제공합니다.

바닥글.js

import React from 'react';

const Footer = () => {
  return (
    <div classname="footer">
      Made with <span>❤️</span> by Abhishek Gurjar
    </div>
  );
};

export default Footer;
*{
  box-sizing: border-box;
}
body{
  font-family: sans-serif;
  margin: 0;
  padding: 0;
}
.navbar {
  padding-inline: 100px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  background-color: red;
}
.search-btn{
  background-color: red;
}
.logo h1{
  font-size: 25px;
  color:black;
  }
.page-list {
  display: flex;
  align-items: center;
  gap: 40px;
}

.page-list a{
  color: white;
  text-decoration: none;
  font-size: 20px;
}
.page-list a:hover{
color: black;
}
.page-list a.active{
  color: black;
}
.search-box{
  box-shadow: rgba(0, 0, 0, 0.35) 0px 5px 15px;
  background-color:white;
  color: gray;
  width: 250px;
  height: 40px;
  border-radius: 50px;
  overflow: hidden;
}
.search-box input{
  width: 200px;
  height: 40px;
  margin-left: 10px;
  border: none;
  outline: none;

}
.home{
  margin-block: 40px;
  margin-inline: 60px;

}
.home h4{
  font-size: 16px;
}


.movies{
  margin-block: 40px;
  margin-inline: 60px;

}
.movies h4{
  font-size: 16px;
}
.cards{
  display: flex;
flex-wrap: wrap;
  align-items:center ;
  justify-content: space-between;
  gap: 10px;
}
.card{
  width:200px;
  height:360px;
  border-radius: 10px;
  overflow: hidden;
  box-shadow: rgba(0, 0, 0, 0.35) 0px 5px 15px;
}
.card img{
  width: 200px;
  height: 290px;
  object-fit: cover;
}
.card h2{
  margin: 10px;
  font-size: 16px;
text-align: center;
}

.series{
  margin-block: 40px;
  margin-inline: 60px;
}
.series h4{
  font-size: 16px;
}
.home{
  margin-block: 40px;
  margin-inline: 60px;

}
.search-results{
  margin-block: 40px;
  margin-inline: 60px;
}
.search-results h4{
  font-size: 16px;
}

.loader{
  min-height: 90vh;
  display: flex;
  align-items: center;
  justify-content: center;
}
/* HTML: <div class="loader"></div> */
.load {
  width: 50px;
  padding: 8px;
  aspect-ratio: 1;
  border-radius: 50%;
  background: #ff1900;
  --_m: 
    conic-gradient(#0000 10%,#000),
    linear-gradient(#000 0 0) content-box;
  -webkit-mask: var(--_m);
          mask: var(--_m);
  -webkit-mask-composite: source-out;
          mask-composite: subtract;
  animation: l3 1s infinite linear;
}
@keyframes l3 {to{transform: rotate(1turn)}}


.movie-detail {
  margin-block: 40px;
  margin-inline: 60px;
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
}
img-box{
  width: 50%;
}
.movie-detail img {
  border-radius: 10px;
width: 330px;
 height: auto;
 object-fit: cover;
 box-shadow: rgba(0, 0, 0, 0.35) 0px 5px 15px;
}

.detail-box{
  width: 50%;
}
.movie-detail p {
  font-size: 18px;
  margin: 10px 0;
}

.movie-detail a {
  display: inline-block;
  margin-top: 20px;
  color: #007bff;
  text-decoration: none;
}

.movie-detail a:hover {
  text-decoration: underline;
}


.footer{
  width: 100%;
  background-color: red;
  text-align: center;
  color: white;
  padding: 20px;
}

라이브 데모

여기에서 Movie Finder 웹사이트의 라이브 데모를 확인하실 수 있습니다.

결론

이번 블로그에서는 React, React Router, Axios를 사용하여 Movie Finder 웹사이트를 만드는 방법을 배웠습니다. 이 프로젝트는 공개 API와 상호 작용하고, React에서 상태를 관리하고, 간단하면서도 기능적인 영화 탐색 경험을 만드는 방법을 보여줍니다.

디자인을 자유롭게 맞춤화하고 사용자 리뷰나 영화 평가와 같은 기능을 추가하여 더욱 역동적으로 만들어 보세요!


크레딧

  • OMDB API
  • 반응
  • 리액트 라우터

작가

Abhishek Gurjar는 실용적이고 기능적인 웹 애플리케이션 제작에 열정을 쏟는 헌신적인 웹 개발자입니다. GitHub에서 더 많은 프로젝트를 확인해 보세요.

위 내용은 React를 사용하여 Movie Finder 웹사이트 구축하기의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
두 개의 이미지와 API : 제품을 다시 칠하는 데 필요한 모든 것두 개의 이미지와 API : 제품을 다시 칠하는 데 필요한 모든 것Apr 15, 2025 am 11:27 AM

최근에 제품 이미지의 색상을 동적으로 업데이트하는 솔루션을 찾았습니다. 따라서 제품 중 하나만 사용하여 다른 방식으로 색칠 할 수 있습니다.

주간 플랫폼 뉴스 : 제 3 자 코드, 수동 혼합 콘텐츠, 가장 느린 연결이있는 국가의 영향주간 플랫폼 뉴스 : 제 3 자 코드, 수동 혼합 콘텐츠, 가장 느린 연결이있는 국가의 영향Apr 15, 2025 am 11:19 AM

이번 주에 라운드 업, Lighthouse는 타사 스크립트에 빛을 비추고 불안한 자원이 안전한 사이트에서 차단되고 많은 국가 연결 속도가 차단됩니다.

직접 비자 스크립트 기반 분석을 호스팅하는 옵션직접 비자 스크립트 기반 분석을 호스팅하는 옵션Apr 15, 2025 am 11:09 AM

사이트에서 방문자 및 사용 데이터를 추적하는 데 도움이되는 분석 플랫폼이 많이 있습니다. 아마도 널리 사용되는 Google 웹 로그 분석

그것은 모두 헤드에있는 모든 것 : React Helmet과 함께 React 전원 사이트의 문서 헤드 관리그것은 모두 헤드에있는 모든 것 : React Helmet과 함께 React 전원 사이트의 문서 헤드 관리Apr 15, 2025 am 11:01 AM

문서 헤드는 웹 사이트에서 가장 화려한 부분이 아닐 수도 있지만 웹 사이트의 성공에 중요합니다.

JavaScript의 Super () 란 무엇입니까?JavaScript의 Super () 란 무엇입니까?Apr 15, 2025 am 10:59 AM

Super ()?를 호출하는 JavaScript를 볼 때 어떤 일이 발생 하는가. 아동 클래스에서는 Super ()를 사용하여 부모의 생성자와 Super를 호출합니다. 그것의 접근

다양한 유형의 기본 JavaScript 팝업 비교다양한 유형의 기본 JavaScript 팝업 비교Apr 15, 2025 am 10:48 AM

JavaScript에는 사용자 상호 작용을위한 특수 UI를 표시하는 다양한 내장 팝업 API가 있습니다. 뛰어나게:

액세스 가능한 웹 사이트를 구축하기가 어려운 이유는 무엇입니까?액세스 가능한 웹 사이트를 구축하기가 어려운 이유는 무엇입니까?Apr 15, 2025 am 10:45 AM

나는 다른 날에 많은 회사들이 액세스 가능한 웹 사이트를 만드는 데 어려움을 겪고있는 이유에 대해 다른 프론트 엔드 사람들과 대화를 나누고있었습니다. 액세스 가능한 웹 사이트가 왜 그렇게 어려운가

'숨겨진'속성은 눈에 띄게 약합니다'숨겨진'속성은 눈에 띄게 약합니다Apr 15, 2025 am 10:43 AM

당신이해야 할 일을 정확하게 수행하는 HTML 속성이 있습니다.

See all articles

핫 AI 도구

Undresser.AI Undress

Undresser.AI Undress

사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover

AI Clothes Remover

사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool

Undress AI Tool

무료로 이미지를 벗다

Clothoff.io

Clothoff.io

AI 옷 제거제

AI Hentai Generator

AI Hentai Generator

AI Hentai를 무료로 생성하십시오.

인기 기사

R.E.P.O. 에너지 결정과 그들이하는 일 (노란색 크리스탈)
4 몇 주 전By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. 최고의 그래픽 설정
4 몇 주 전By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. 아무도들을 수없는 경우 오디오를 수정하는 방법
4 몇 주 전By尊渡假赌尊渡假赌尊渡假赌
WWE 2K25 : Myrise에서 모든 것을 잠금 해제하는 방법
1 몇 달 전By尊渡假赌尊渡假赌尊渡假赌

뜨거운 도구

SublimeText3 Mac 버전

SublimeText3 Mac 버전

신 수준의 코드 편집 소프트웨어(SublimeText3)

PhpStorm 맥 버전

PhpStorm 맥 버전

최신(2018.2.1) 전문 PHP 통합 개발 도구

WebStorm Mac 버전

WebStorm Mac 버전

유용한 JavaScript 개발 도구

Atom Editor Mac 버전 다운로드

Atom Editor Mac 버전 다운로드

가장 인기 있는 오픈 소스 편집기

Dreamweaver Mac版

Dreamweaver Mac版

시각적 웹 개발 도구