In diesem Blog werden wir durch den Prozess der Erstellung einer Movie Finder-Website mit React und der OMDB-API gehen. Auf der Website können Benutzer Filme nach Kategorien wie „Avengers“, „Star Wars“ und „Serien“ durchsuchen und mithilfe spezifischer Suchanfragen nach Filmen suchen. Jeder Film verfügt über eine Detailseite, sodass Sie ganz einfach mehr über Ihre Lieblingsfilme erfahren können.
Movie Finder-Website ermöglicht Benutzern Folgendes:
Hier ist die Verzeichnisstruktur für das Projekt:
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
Klonen Sie das Repository:
git clone https://github.com/abhishekgurjar-in/movie-finder.git cd movie-finder
Abhängigkeiten installieren:
npm install
Holen Sie sich Ihren API-Schlüssel von der OMDB-API.
Erstellen Sie eine .env-Datei im Projektstamm und fügen Sie Ihren API-Schlüssel hinzu:
REACT_APP_OMDB_API_KEY=yourapikey
Führen Sie das Projekt aus:
npm start
Die Startseite zeigt zwei Kategorien von Filmen: Avengers und Star Wars. Wenn der Benutzer auf eine Filmkarte klickt, wird er zur detaillierten Filmseite weitergeleitet.
Code-Snippet von 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={movie.Poster} alt={movie.Title} /> <h2>{movie.Title}</h2> </div> )) ) : ( <p>No movies found.</p> )} </div> ) ); return ( <> <div className="home"> <div className="movie-category"> <h4>Avengers Movies</h4> {renderMovies(avengersMovies, loadingAvengers)} </div> <br /> <br /> <div className="movie-category"> <h4>Star Wars Movies</h4> {renderMovies(starWarsMovies, loadingStarWars)} </div> </div> <Movies /> <Series /> </> ); }; export default Home;
Der Benutzer kann über die Suchleiste oben auf der Website nach jedem Film suchen. Suchergebnisse werden basierend auf der Anfrage des Benutzers von der OMDB-API abgerufen.
Code-Snippet von 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>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={movie.Poster} alt={movie.Title} /> <h2>{movie.Title}</h2> </div> )) ) : ( <p>No results found.</p> )} </div> )} </div> ); }; export default SearchResults;
Wenn ein Benutzer auf einen Film klickt, wird er zur Filmdetailseite weitergeleitet. Auf dieser Seite werden der Titel, das Poster, die Handlung, die Schauspieler und mehr des Films angezeigt.
Codeausschnitt aus 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>{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={movie.Poster} alt={movie.Title} /> </div> </div> ); }; export default MovieDetail;
Movies.js und Series.js werden jeweils Filme und Fernsehserien aufgeführt.
Codeausschnitt aus 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>Movies</h2> <div className="cards"> {movies.map(movie => ( <div key={movie.imdbID} className="card" onClick={() => handleCardClick(movie.imdbID)}> <img src={movie.Poster} alt={movie.Title} /> <h3>{movie.Title}</h3> </div> ))} </div> </div> ); }; export default Movies;
Codeausschnitt aus 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>TV Series</h2> <div className="cards"> {series.map(show => ( <div key={show.imdbID} className="card" onClick={() => handleCardClick(show.imdbID)}> <img src={show.Poster} alt={show.Title} /> <h3>{show.Title}</h3> </div> ))} </div> </div> ); }; export default Series;
Mit der Navbar-Komponente können Benutzer zwischen verschiedenen Seiten navigieren und eine Suche durchführen.
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>Movie Finder</h1> </div> <div className="page-list"> <NavLink to="/"> <h4>Home</h4> </NavLink> <NavLink to="/movies"> <h4>Movies</h4> </NavLink> <NavLink to="/series"> <h4>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> </Link> </div> </div> ); }; export default Navbar;
Die Footer-Komponente stellt eine einfache Fußzeilennachricht bereit.
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; }
Sie können sich hier die Live-Demo der Movie Finder-Website ansehen.
In diesem Blog haben wir gelernt, wie man mit React, React Router und Axios eine Movie Finder-Website erstellt. Dieses Projekt zeigt, wie man mit einer öffentlichen API interagiert, den Status in React verwaltet und ein einfaches, aber funktionales Erlebnis beim Durchsuchen von Filmen erstellt.
Fühlen Sie sich frei, das Design anzupassen und weitere Funktionen wie Benutzerrezensionen oder Filmbewertungen hinzuzufügen, um es dynamischer zu gestalten!
Abhishek Gurjar ist ein engagierter Webentwickler, der sich mit der Entwicklung praktischer und funktionaler Webanwendungen beschäftigt. Schauen Sie sich weitere seiner Projekte auf GitHub an.
Das obige ist der detaillierte Inhalt vonErstellen einer Movie Finder-Website mit React. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!