使用React和API的电影搜索引擎
在本文中,我们将使用ReactJS创建电影搜索引擎。在这个电影搜索引擎中,用户可以搜索他们想要了解的电影,并且搜索引擎将根据关键字获取电影列表,并以卡片形式显示结果。初始加载了一个默认搜索来显示电影。
该项目主要实现了类的功能组件,并相应地管理状态。应用程序用户使用搜索栏搜索电影,然后应用程序返回有关搜索电影的信息。搜索电影和获取搜索电影结果的逻辑是使用JSX实现的。
让我们交互地看一下我们最终项目的样子:
使用的技术 / 先决条件:
- ReactJS
- CSS
- JSX
- React中的功能组件
方法
使用ReactJS创建电影搜索引擎时,我们设置项目,为用户输入创建SearchBar组件,使用useState钩子来管理搜索词的状态,使用useEffect钩子从API获取电影数据,使用JSX在MovieList组件中渲染电影信息,将组件组合在主App组件中,使用CSS为组件添加样式,并通过运行应用程序并在搜索栏中输入电影标题来测试应用程序。
项目结构:
创建应用程序的步骤:
步骤1: 在VSCode IDE中使用以下命令设置React项目。
npx create-react-app <<name of project>>
步骤2: 通过执行以下命令导航到新创建的项目文件夹。
cd <<Name_of_project>>
步骤3: 创建一个名为MovieCard.jsx的文件。我们将使用现有的App.js和App.css文件来执行应用程序的行为和样式。
将下面提到的代码写入不同的文件中(每个代码块的第一行中提到了文件的名称)。
示例:
- index.html: 这是在public文件夹中自动生成的文件,我们只需在其标签中导入图标包即可。
- App.js: 该文件导入了电影组件并将其导出。
- MovieCard.jsx: 此文件以卡片或网格形式显示电影的表示形式。使用此文件将调用API来获取搜索到的电影。
- App.css: 此文件包含电影搜索引擎元素的设计。
// App.js
import React, { useState } from 'react';
import { useEffect } from 'react';
import './App.css';
import MovieCard from './MovieCard';
const API_URL = 'https://omdbapi.com?apikey=fe2f6c44';
const App = () => {
const [movies, setMovies] = useState([]);
const [searchTerm, setSearchTerm] = useState([]);
const searchMovies = async (title) => {
const response = await fetch(`{API_URL}&s={title}`);
const data = await response.json();
setMovies(data.Search);
}
useEffect(() => {
searchMovies('SpiderMan');
}, []);
return (
<div className="app">
<h1>GeeksforGeeks's Movie Center</h1>
<div className="search">
<input
placeholder="Search for Movies"
value={searchTerm}
onChange={(e) => { setSearchTerm(e.target.value) }}
/>
<img
src=
"https://media.geeksforgeeks.org/wp-content/uploads/20230626112934/search.png"
alt="search icon"
onClick={() => searchMovies(searchTerm)}
/>
</div>
{
movies?.length > 0
? (<div className="container">
{movies.map((movie) => (
<MovieCard movie={movie} />
))}
</div>) : (
<div className="empty">
<h2>No Movies found</h2>
</div>
)
}
</div>
);
}
export default App;
MovieCard.jsx
// MovieCard.jsx
import React from 'react';
// import App from './App';
const MovieCard = ({ movie }) => {
return (
<div className="movie">
<div>
<p>{movie.Title}</p>
</div>
<div>
<img src={movie.Poster !== 'N/A' ? movie.Poster : "https://via.placeholder.com/400"} alt={movie.Title} />
</div>
<div>
<span>{movie.Type}</span>
<h3>{movie.Title}</h3>
</div>
</div>
)
}
export default MovieCard;
HTML
<!--index.html-->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<meta name="description" content="Web site created using create-react-app" />
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<title>GeeksforGeeks Movie's Center</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
</body>
</html>
CSS
/* App.css */
@import url("https://fonts.googleapis.com/css?family=Roboto+Slab:100,300,400,700");
@import url("https://fonts.googleapis.com/css?family=Raleway:300,300i,400,400i,500,500i,600,600i,700,700i,800,800i,900,900i");
* {
margin: 0;
border: 0;
box-sizing: border-box;
}
:root {
--font-roboto: "Roboto Slab", serif;
--font-raleway: "Raleway", sans-serif;
}
body {
font-family: var(--font-roboto);
background-color: #212426;
}
.app {
padding: 4rem;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
}
h1 {
font-size: 3rem;
letter-spacing: 0.9px;
background: linear-gradient(90deg,
rgba(249, 211, 180, 1) 0%,
rgba(249, 211, 180, 0) 100%);
background-clip: text;
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
width: fit-content;
}
.search {
width: 71%;
margin: 4rem 0 2rem;
display: flex;
align-items: center;
justify-content: center;
padding: 1.5rem 1.75rem;
border-radius: 3rem;
background: #1f2123;
-webkit-box-shadow: 5px 5px 7px #1c1d1f, -5px -5px 7px #222527;
box-shadow: 5px 5px 7px #1c1d1f, -5px -5px 7px #222527;
}
.search input {
flex: 1;
border: none;
font-size: 1.5rem;
font-family: var(--font-raleway);
font-weight: 500;
padding-right: 1rem;
outline: none;
color: #a1a1a1;
background: #1f2123;
}
.search img {
width: 35px;
height: 35px;
cursor: pointer;
}
.empty {
width: 100%;
margin-top: 3rem;
display: flex;
justify-content: center;
align-items: center;
}
.empty h2 {
font-size: 1.25rem;
color: #f9d3b4;
font-family: var(--font-raleway);
}
.container {
width: 100%;
margin-top: 3rem;
display: flex;
justify-content: center;
align-items: center;
flex-wrap: wrap;
}
.movie {
width: 310px;
height: 460px;
margin: 1.5rem;
position: relative;
border-radius: 12px;
overflow: hidden;
border: none;
transition: all 0.4s cubic-bezier(0.175, 0.885, 0, 1);
box-shadow: 0px 13px 10px -7px rgba(0, 0, 0, 0.1);
}
.movie div:nth-of-type(1) {
position: absolute;
padding: 16px;
width: 100%;
opacity: 0;
top: 0;
color: #f9d3b4;
}
.movie:hover {
box-shadow: 0px 30px 18px -8px rgba(0, 0, 0, 0.1);
transform: scale(1.05, 1.05);
}
.movie div:nth-of-type(2) {
width: 100%;
height: 100%;
}
.movie div:nth-of-type(2) img {
height: 100%;
width: 100%;
}
.movie div:nth-of-type(3) {
z-index: 2;
background-color: #343739;
padding: 16px 24px 24px 24px;
position: absolute;
bottom: 0;
right: 0;
left: 0;
}
.movie div:nth-of-type(3) span {
font-family: "Raleway", sans-serif;
text-transform: uppercase;
font-size: 13px;
letter-spacing: 2px;
font-weight: 500;
color: #f0f0f0;
}
.movie div:nth-of-type(3) h3 {
margin-top: 5px;
font-family: "Roboto Slab", serif;
color: #f9d3b4;
}
.movie:hover div:nth-of-type(2) {
height: 100%;
opacity: 0.3;
}
.movie:hover div:nth-of-type(3) {
background-color: transparent;
}
.movie:hover div:nth-of-type(1) {
opacity: 1;
}
@media screen and (max-width: 600px) {
.app {
padding: 4rem 2rem;
}
.search {
padding: 1rem 1.75rem;
width: 100%;
}
.search input {
font-size: 1rem;
}
.search img {
width: 20px;
height: 20px;
}
}
@media screen and (max-width: 400px) {
.app {
padding: 4rem 1rem;
}
h1 {
font-size: 2rem;
}
.container {
margin-top: 2rem;
}
.movie {
width: "100%";
margin: 1rem;
}
}
运行应用的步骤:
1. 在终端中执行以下命令。
npm start
2. 打开网页浏览器,并在地址栏中输入以下URL。
http://localhost:3000/
输出: