Heim  >  Artikel  >  Web-Frontend  >  Erstellen einer Movie Finder-Website mit React

Erstellen einer Movie Finder-Website mit React

DDD
DDDOriginal
2024-09-13 12:39:34545Durchsuche

Building a Movie Finder Website using React

Einführung

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.

Projektübersicht

Movie Finder-Website ermöglicht Benutzern Folgendes:

  • Durchsuchen Sie Kategorien wie Avengers und Star Wars.
  • Suchen Sie nach Filmen anhand von Schlüsselwörtern.
  • Detaillierte Filminformationen anzeigen (Poster, Genre, Regisseur, Schauspieler und mehr).
  • Navigieren Sie einfach durch die Website mit einem klaren, modernen Design.

Merkmale

  • Daten dynamisch mithilfe der OMDB-API abrufen.
  • Responsives Design für ein besseres Benutzererlebnis.
  • Suchfunktion, die sofortige Ergebnisse liefert.
  • Anzeigen werden geladen, während Daten abgerufen werden.
  • Details zu einzelnen Filmen finden Sie auf einer separaten Seite.

Verwendete Technologien

  • React: Frontend-Bibliothek zum Erstellen von UI-Komponenten.
  • React Router: Für Navigation und Routing.
  • Axios: Zum Senden von HTTP-Anfragen an die OMDB-API.
  • OMDB-API: Zum Abrufen von Filmdetails.
  • CSS: Zum Gestalten der Anwendung.

Projektstruktur

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

Installation

  1. Klonen Sie das Repository:

    git clone https://github.com/abhishekgurjar-in/movie-finder.git
    cd movie-finder
    
  2. Abhängigkeiten installieren:

    npm install
    
  3. Holen Sie sich Ihren API-Schlüssel von der OMDB-API.

  4. Erstellen Sie eine .env-Datei im Projektstamm und fügen Sie Ihren API-Schlüssel hinzu:

    REACT_APP_OMDB_API_KEY=yourapikey
    
  5. Führen Sie das Projekt aus:

    npm start
    

Verwendung

1. Startseite

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 ? (
      391706c98a6bb525cf4d3f804c3e9b3baac6cad6c09b9658b5b35f3523d88d1116b28748ea4df4d9c2150843fecfba6816b28748ea4df4d9c2150843fecfba68
    ) : (
      708b1d1285701e251e9fa1f2193b7d63
        {movies.length > 0 ? (
          movies.map((movie) => (
            12728e1adecf83573e180dc578e2e2c2 handleCardClick(movie.imdbID)}>
              53f77bfc03dd61d765abffefdb992f4f
              c1a436a314ed609750bd7c7d319db4da{movie.Title}2e9b454fa8428549ca2e64dfac4625cd
            16b28748ea4df4d9c2150843fecfba68
          ))
        ) : (
          e388a4556c0f65e1904146cc1a846beeNo movies found.94b3e26ee717c64999d7867364b1b4a3
        )}
      16b28748ea4df4d9c2150843fecfba68
    )
  );

  return (
    a8093152e673feb7aba1828c43532094
      5e12fe6a884c5486b6a8efaa94283304
        9b0bcc9b98322501402178b0f3be9a1e
          3f7b3decd2dcafb07b84d2d3985d9f40Avengers Movies0f6dfd1e3624ce5465eb402e300e01ae
          {renderMovies(avengersMovies, loadingAvengers)}
        16b28748ea4df4d9c2150843fecfba68
        df250b2156c434f3390392d09b1c9563
        df250b2156c434f3390392d09b1c9563
        9b0bcc9b98322501402178b0f3be9a1e
          3f7b3decd2dcafb07b84d2d3985d9f40Star Wars Movies0f6dfd1e3624ce5465eb402e300e01ae
          {renderMovies(starWarsMovies, loadingStarWars)}
        16b28748ea4df4d9c2150843fecfba68
      16b28748ea4df4d9c2150843fecfba68
      52f3849cf2c3f31cc82a4e8b32ced1d3
      ecdc054e702196f465a773413a599e82
    5f557f62ae7ac7a14e0b1cb564790dfc
  );
};

export default Home;

2. Suchfunktion

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 (
    bf6ea6bca350fbd36c62942eeadc3f36
      3f7b3decd2dcafb07b84d2d3985d9f40Search Results for "{query}"0f6dfd1e3624ce5465eb402e300e01ae
      {loading ? (
        391706c98a6bb525cf4d3f804c3e9b3baac6cad6c09b9658b5b35f3523d88d1116b28748ea4df4d9c2150843fecfba6816b28748ea4df4d9c2150843fecfba68  // Loader
      ) : (
        708b1d1285701e251e9fa1f2193b7d63
          {movies.length > 0 ? (
            movies.map((movie) => (
              12728e1adecf83573e180dc578e2e2c2 handleCardClick(movie.imdbID)}>
                53f77bfc03dd61d765abffefdb992f4f
                c1a436a314ed609750bd7c7d319db4da{movie.Title}2e9b454fa8428549ca2e64dfac4625cd
              16b28748ea4df4d9c2150843fecfba68
            ))
          ) : (
            e388a4556c0f65e1904146cc1a846beeNo results found.94b3e26ee717c64999d7867364b1b4a3
          )}
        16b28748ea4df4d9c2150843fecfba68
      )}
    16b28748ea4df4d9c2150843fecfba68
  );
};

export default SearchResults;

3. Filmdetailseite

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 391706c98a6bb525cf4d3f804c3e9b3b
    aac6cad6c09b9658b5b35f3523d88d1116b28748ea4df4d9c2150843fecfba68
  16b28748ea4df4d9c2150843fecfba68;
  if (!movie) return bc3517ed53a2992e46268da16e3f760bNo movie data found!16b28748ea4df4d9c2150843fecfba68;

  return (
    5d4fb5b3e2c1bf52ca40540d9f64ecf6

7d32ff64584c41174c506c75fd1c43f8
4a249f0d628e2318394fd9b75b4636b1{movie.Title}473f0a7621bec819994bb5020d29372a
e388a4556c0f65e1904146cc1a846bee8e99a69fbe029cd4e2b854e244eab143Year:128dba7a3a77be0113eb0bea6ea0a5d0 {movie.Year}94b3e26ee717c64999d7867364b1b4a3
      e388a4556c0f65e1904146cc1a846bee8e99a69fbe029cd4e2b854e244eab143Rating:128dba7a3a77be0113eb0bea6ea0a5d0 {movie.imdbRating}94b3e26ee717c64999d7867364b1b4a3
      e388a4556c0f65e1904146cc1a846bee8e99a69fbe029cd4e2b854e244eab143Genre:128dba7a3a77be0113eb0bea6ea0a5d0 {movie.Genre}94b3e26ee717c64999d7867364b1b4a3
      e388a4556c0f65e1904146cc1a846bee8e99a69fbe029cd4e2b854e244eab143Director:128dba7a3a77be0113eb0bea6ea0a5d0 {movie.Director}94b3e26ee717c64999d7867364b1b4a3
      e388a4556c0f65e1904146cc1a846bee8e99a69fbe029cd4e2b854e244eab143Actors:128dba7a3a77be0113eb0bea6ea0a5d0 {movie.Actors}94b3e26ee717c64999d7867364b1b4a3
      e388a4556c0f65e1904146cc1a846bee8e99a69fbe029cd4e2b854e244eab143Plot:128dba7a3a77be0113eb0bea6ea0a5d0 {movie.Plot}94b3e26ee717c64999d7867364b1b4a3
      e388a4556c0f65e1904146cc1a846bee8e99a69fbe029cd4e2b854e244eab143Runtime:128dba7a3a77be0113eb0bea6ea0a5d0 {movie.Runtime}94b3e26ee717c64999d7867364b1b4a3
      e388a4556c0f65e1904146cc1a846bee8e99a69fbe029cd4e2b854e244eab143Language:128dba7a3a77be0113eb0bea6ea0a5d0 {movie.Language}94b3e26ee717c64999d7867364b1b4a3
      e388a4556c0f65e1904146cc1a846bee8e99a69fbe029cd4e2b854e244eab143Country:128dba7a3a77be0113eb0bea6ea0a5d0 {movie.Country}94b3e26ee717c64999d7867364b1b4a3
      e388a4556c0f65e1904146cc1a846bee8e99a69fbe029cd4e2b854e244eab143Awards:128dba7a3a77be0113eb0bea6ea0a5d0 {movie.Awards}94b3e26ee717c64999d7867364b1b4a3
16b28748ea4df4d9c2150843fecfba68
    bcf6b949990d2b26854fc1a0235e7896
    53f77bfc03dd61d765abffefdb992f4f
    16b28748ea4df4d9c2150843fecfba68
    16b28748ea4df4d9c2150843fecfba68
  );
};

export default MovieDetail;

4. Film- und Serienseiten

Auf den Seiten

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 (
    d40b792c730e4d11d0eca74a10366575
      c1a436a314ed609750bd7c7d319db4daMovies2e9b454fa8428549ca2e64dfac4625cd
      708b1d1285701e251e9fa1f2193b7d63
        {movies.map(movie => (
          12728e1adecf83573e180dc578e2e2c2 handleCardClick(movie.imdbID)}>
            53f77bfc03dd61d765abffefdb992f4f
            684271ed9684bde649abda8831d4d355{movie.Title}39528cedfa926ea0c01e69ef5b2ea9b0
          16b28748ea4df4d9c2150843fecfba68
        ))}
      16b28748ea4df4d9c2150843fecfba68
    16b28748ea4df4d9c2150843fecfba68
  );
};

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 (
    31838116f0659c8e0fe2d7d1854d0e7a
      c1a436a314ed609750bd7c7d319db4daTV Series2e9b454fa8428549ca2e64dfac4625cd
      708b1d1285701e251e9fa1f2193b7d63
        {series.map(show => (
          01c7d619b10fabc0744128b826b29a0f handleCardClick(show.imdbID)}>
            a9c0cac5f8f3bc0104ebd6d33bb9bd98
            684271ed9684bde649abda8831d4d355{show.Title}39528cedfa926ea0c01e69ef5b2ea9b0
          16b28748ea4df4d9c2150843fecfba68
        ))}
      16b28748ea4df4d9c2150843fecfba68
    16b28748ea4df4d9c2150843fecfba68
  );
};

export default Series;

5. Navbar-Komponente

Mit der Navbar-Komponente können Benutzer zwischen verschiedenen Seiten navigieren und eine Suche durchführen.

Navbar.js aktualisiert

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 (
    6de5cdabed8c37e65ec07ad5a9b8f878
      788a37ae874cfc6a3ed79faf72b77879
        4a249f0d628e2318394fd9b75b4636b1Movie Finder473f0a7621bec819994bb5020d29372a
      16b28748ea4df4d9c2150843fecfba68

      48f38cae923f5e26c602cafad0cbf526
        7a33e57c3b200f2f5ecc2e455318e8cf
          3f7b3decd2dcafb07b84d2d3985d9f40Home0f6dfd1e3624ce5465eb402e300e01ae
        adb9ac3aead1d3fba02ca688b8636d1b
        652dfcca303e1ed15c65622e15127ba2
          3f7b3decd2dcafb07b84d2d3985d9f40Movies0f6dfd1e3624ce5465eb402e300e01ae
        adb9ac3aead1d3fba02ca688b8636d1b
        d63227fa461236d17a6381d446ab43a0
          3f7b3decd2dcafb07b84d2d3985d9f40TV Series0f6dfd1e3624ce5465eb402e300e01ae
        adb9ac3aead1d3fba02ca688b8636d1b
      16b28748ea4df4d9c2150843fecfba68
      a349cf54cf26717db21be5f2029cbdd5
        a09ba7022bc6a6807a1896f2a858385a setSearchQuery(e.target.value)}
          onKeyDown={handleSearch}
        />
        e4f7f070cfb179e9f270abf5ddd9c301
          bb9345e55eb71822850ff156dfde57c8Search65281c5ac262bf6d81768915a4a77ac0
        06f735b502bd5273dad825215f7c405b
      16b28748ea4df4d9c2150843fecfba68
    16b28748ea4df4d9c2150843fecfba68
  );
};

export default Navbar;

6. Fußzeilenkomponente

Die Footer-Komponente stellt eine einfache Fußzeilennachricht bereit.

Footer.js

import React from 'react';

const Footer = () => {
  return (
    c36ce888baa3a5bd9bc4a4919fc19de1
      Made with 45a2772a6b6107b401db3c9b82c049c2❤️54bdf357c58b8a65c66d7c19c8e4d114 by Abhishek Gurjar
    16b28748ea4df4d9c2150843fecfba68
  );
};

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: 9c7dadb03dddabc8a9ba04a02322601d16b28748ea4df4d9c2150843fecfba68 */
.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;
}

Live-Demo

Sie können sich hier die Live-Demo der Movie Finder-Website ansehen.

Abschluss

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!


Credits

  • OMDB-API
  • Reagieren
  • React Router

Autor

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!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn