# React project movie-app
###### tags: `Javascript, React`
主要操作 react 跟著課程手把手把這個 project 完成,使用到 useState, useEffect ,練習 fetch API 以及 render 到頁面上
# [成品網址](https://chiehliu.github.io/movie-app/)
## 示意圖

# 功能:
* 可以搜尋電影
* 顯示電影大綱
* 顯示電影評分
* 有 default 圖片如果找不到的話
# JS 程式碼
## 使用的 API
* APIURL 主要使用來呈現 - 使用歡迎度來分類的第一頁的電影內容
* SEARCHAPI 則是可以在最後面的 query="" 字串串接上內容來搜尋資源
* IMGPATH 的部分就是呈現圖片
```javascript=
const APIURL =
"https://api.themoviedb.org/3/discover/movie?sort_by=popularity.desc&api_key=04c35731a5ee918f014970082a0088b1&page=1";
const SEARCHAPI =
"https://api.themoviedb.org/3/search/movie?&api_key=04c35731a5ee918f014970082a0088b1&query=";
const IMGPATH = "https://image.tmdb.org/t/p/w1280";
```
## App.js
```javascript=
import React, { useEffect, useState } from 'react';
import Movie from './components/Movie';
const APIURL =
"https://api.themoviedb.org/3/discover/movie?sort_by=popularity.desc&api_key=04c35731a5ee918f014970082a0088b1&page=1";
const SEARCHAPI =
"https://api.themoviedb.org/3/search/movie?&api_key=04c35731a5ee918f014970082a0088b1&query=";
function App() {
const [movies, setMovies] = useState([]);
const [searchTerm, setSearchTerm] = useState('');
useEffect(() => {
fetch(APIURL)
.then(res => res.json())
.then(data => {
console.log(data);
// 這邊是目前第一頁呈現的所有電影內容並且指派給 movies
setMovies(data.results);
})
}, [])
// 主要處理 submit 後利用使用者輸入的內容加上搜尋API 重新 fetch 內容並且更新 state
const handleOnSubmit = (e) => {
e.preventDefault();
if (searchTerm) {
fetch(SEARCHAPI + searchTerm)
.then(res => res.json())
.then(data => {
console.log(data);
// 這邊把搜尋到的 data.results 更新到 movies,因此頁面呈現只剩下搜尋的內容
setMovies(data.results);
});
// 當 movies 被更新後搜尋欄位則被清空
setSearchTerm('');
}
}
// 這邊函式主要處理使用者在 search 輸入的內容要更新到 state searchTerm 裡面
const handleOnChange = (e) => {
setSearchTerm(e.target.value)
}
return (
<div>
<header>
// 主要會在 form 表單加上 submit 事件監聽
<form onSubmit={handleOnSubmit}>
<input type="search" className="search" placeholder="Search..."
value={searchTerm}
onChange={handleOnChange}
/>
</form>
</header>
<div className="movie-container">
// 使用 map 印出內容傳到 <Movie> 內部當作 props 傳遞給 movie.js component
{movies && movies.map((movie) => <Movie {...movie} key={movie.id} />
)}
</div>
</div>
);
}
export default App;
```
### 從 API 取得 Movie 的物件
* 取得物件(data)之後得從 json 轉回物件格式
* 接下來 setMovies 給 useState 中的 movies 使用
```javascript=
useEffect(() => {
fetch(APIURL)
.then(res => res.json())
.then(data => {
console.log(data);
setMovies(data.results);
})
}, [])
```
### render 資料上去 DOM
成品會有兩個部分 Search, movie
1. Search
* 針對整個 form 做 onSubmit 事件處理 並使用`handleOnSubmit`
在 submit 時再次執行 fetch 這次的 url 會加入 搜尋用url+searchTerm ,最後使用找到的資料更新 DOM(就會只剩搜尋到的內容)
* 對 value 的屬性做動態處理(上大括號)
* 針對整個 form 做 onChange 事件處理 並使用`handleOnChange`
會把目前使用者輸入在 input 的內容更新進去 searchTerm
2. movie
使用 `&&` 運算子判斷式 如果 movies 不為空就正常 render 出 movies 內容
```javascript=
return (
<div>
<header>
<form onSubmit={handleOnSubmit}>
<input type="search" className="search" placeholder="Search..."
value={searchTerm}
onChange={handleOnChange}
/>
</form>
</header>
<div className="movie-container">
{movies && movies.map((movie) => <Movie {...movie} key={movie.id} />
)}
</div>
</div>
);
```
## Movie.js
當作子 component ,接收來自 App.js 的 props 使用解構的方式提取 results 的內容 poster_path, title, overview, vote_average 來呈現到瀏覽器上
```javascript=
const IMGPATH = "https://image.tmdb.org/t/p/w1280";
const Movie = ({ poster_path, title, overview, vote_average }) => {
const setVoteClass = (vote) => {
if (vote >= 8) {
return 'green'
} else if (vote >= 6) {
return 'orange'
} else {
return "red"
}
}
return (
<div className="movie">
<img src={poster_path ? (IMGPATH + poster_path) : 'https://images.unsplash.com/photo-1485846234645-a62644f84728?ixlib-rb-1.2.1&ixid=eyjhcHBfawQiOjEyMDd9&auto=format&fit=crop&w=1480&q=80'} alt={title} />
<div className="movie-info">
<h3>{title}</h3>
<span className={`tag ${setVoteClass(vote_average)}`}>{vote_average}</span>
</div>
<div className="movie-over">
<h2>Overview:</h2>
<p>{overview}</p>
</div>
</div>
);
}
export default Movie;
```
### 預設圖片設置(如果電影圖片沒有正常顯示的話)
使用三元運算子操作 poster_path 是否為 true,如果為真則正常顯示`IMGPATH + poster_path` 為 false 的話顯示一張圖片的路徑當作預設圖片
```javascript=
<img src={poster_path ? (IMGPATH + poster_path) : 'https://images.unsplash.com/photo-1485846234645-a62644f84728?ixlib-rb-1.2.1&ixid=eyjhcHBfawQiOjEyMDd9&auto=format&fit=crop&w=1480&q=80'} alt={title} />
```
### 判斷式
處理顯示數字的顏色,針對 className 做函式操作添加的 class tag