# Netflix - React、Redux (ㄧ)
### 環境建置
> $ npx creat-react-app netflix-build --template redux
### Firebase
[firebase](https://firebase.google.com/)
註冊一個帳號,點選右上角 ==前往主控台==,新增專案
繼續之後點選 </> (網頁),跟著步驟下一步
記得勾選`一併為這個應用程式設定 Firebase 代管功能` ,因為之後要部署此應用程式
###### install Firebase CLI
> $ sudo npm install -g firebase-tools
完成之後,Firebase SDK snippet 勾選 config
複製此段代碼到專案建立一個firebase.js,之後會用到
```javascript=
const firebaseConfig = {
apiKey: "AIzaSyA3OyAW0HLSX3R6s-dJRogcUEq9OJ-DxQ8",
authDomain: "test-94387.firebaseapp.com",
projectId: "test-94387",
storageBucket: "test-94387.appspot.com",
messagingSenderId: "374698696816",
appId: "1:374698696816:web:691ca1e26039b7ad6e94b5"
};
```
### TMDB拿取api__key
1. 使用TMDB API除了要先註冊使用者帳號之外還要再取得API Key,登入帳號後到大頭照那邊點一下,接著點選Settings到設定頁面。
2. 進入Settings頁面後可以看到API的選項,點進去後可以看到指示,依指示進行填資料、送出資料。選擇Web送出資料之後會看到大頭照旁邊的小鈴鐺亮起,點進去會看到自己的API Key送來了。
3. Settings的API頁面,也會看到自己的API Key出現在這裡。
### axios建置
Axios特性
1、可以在瀏覽器中發送 XMLHttpRequests
2、可以在 node.js 發送 http 請求
3、支持 Promise API
4、攔截請求和響應
5、轉換請求數據和響應數據
6、能夠取消請求
7、自動轉換 JSON 數據
8、客戶端支持保護安全免受 XSRF 攻擊
原文網址:https://kknews.cc/code/rl8leyo.html
> $ yarn add axios
建立一個axios.js
```javascript=
import axios from "axios";
const instance = axios.create({
baseURL: "https://api.themoviedb.org/3",
// 需要 TMDB API的網址
});
export default instance;
```
在這之前先仔細閱讀了一下[TMDB API](https://developers.themoviedb.org/3/getting-started/introduction/)文件
建立一個Requests.js
```javascript=
const API_KEY = "523883aef3c6707e0d55a6077e404958";
const requests = {
fetchTrending: `/trending/all/week?api_key=${API_KEY}&language=en-US`,
fetchNexflixOriginals: `/discover/tv?api_key=${API_KEY}&with_networks=213&language=en-US`,
fetchTopRated: `/movie/top_rated?api_key=${API_KEY}&language=en-US`,
fetchActionMovie: `/discover/movie?api_key=${API_KEY}&with_genres=28`,
fetchComedyMovie: `/discover/movie?api_key=${API_KEY}&with_genres=35`,
fetchHorrorMovie: `/discover/movie?api_key=${API_KEY}&with_genres=27`,
fetchRomanceMovie: `/discover/movie?api_key=${API_KEY}&with_genres=10749`,
fetchDocumentaries: `/discover/movie?api_key=${API_KEY}&with_genres=99`,
};
export default requests;
```
在[TMDb genre ID values](https://www.reddit.com/r/radarr/comments/70egj8/tmdb_genre_id_values/)找到相關電影類型,方便之後頁面分類。
### React UI
> $ yarn start
開啟一個local端3000
開啟App.js,create component `<HomeScreen />`,建立一個首頁UI
在<HomeScreen />裡有 `<Nav />、<Banner />、<Row />` component
### <Nav />
在`<Nav />`
```javascript=
const [show, handleShow] = useState(false);
const transitionNavBar = () => {
if (window.scrollY > 100) {
handleShow(true);
} else {
handleShow(false);
}
};
useEffect(() => {
window.addEventListener("scroll", transitionNavBar);
return () => window.removeEventListener("scroll", transitionNavBar);
}, []);
```
```javascript=
<div className={`nav ${show && "nav__black"}`}>
```
在css裡`nav position:fixed`置頂最上方,`nav__black background-color: black`
就可以往下捲軸時超過100,nav的背景就為黑色
---
### <Banner />
在`<Banner />` banner__description裡有個小技巧,可以用一個function讓過多的文字以 ... 呈現
```javascript=
function truncate(string, n) {
return string?.length > n ? string.substr(0, n - 1) + "..." : string;
}
```
```javascript=
<h1 className="banner__description">
{truncate(movie?.overview, 150)}
</h1>
```
:::warning
如果description超過150個字,就以 "..."取代。
:::
> 在Banner頁面裡,拿取TMDB API資料,以隨機方式切換電影資訊
>
```javascript=
const [movie, setMovie] = useState([]);
useEffect(() => {
async function fetchData() {
const request = await axios.get(requests.fetchNexflixOriginals);
setMovie(
request.data.results[
Math.floor(Math.random() * request.data.results.length - 1)
]
);
return request;
}
fetchData();
}, []);
```
:::warning
TMDB API裡圖片的取得有些限制,必須先指定欲取得的圖片尺寸,才能夠取得圖片資料。
尺寸的URL為:https://image.tmdb.org/t/p/+圖片url

```
backgroundImage:
`url("https://image.tmdb.org/t/p/original/${movie?.backdrop_path}")`
```
:::
---
### <HomeScreen />
`import requests from "../Requests"`
```javascript=
function HomeScreen() {
return (
<div className="homescreen">
<Nav />
<Banner />
<Row
title="NEXFLIX ORIGINALS"
fetchUrl={requests.fetchNexflixOriginals}
isLargeRow
/>
<Row title="Trending Now" fetchUrl={requests.fetchTrending} />
<Row title="Top Rated" fetchUrl={requests.fetchTopRated} />
<Row title="Action Movies" fetchUrl={requests.fetchActionMovie} />
<Row title="Comedy Movie" fetchUrl={requests.fetchComedyMovie} />
<Row title="HorrorMovie" fetchUrl={requests.fetchHorrorMovie} />
<Row title="Romance Movie" fetchUrl={requests.fetchRomanceMovie} />
<Row title="Documentaries" fetchUrl={requests.fetchDocumentaries} />
</div>
);
}
```
### <Row />
`import axios from "./axios"`
```javascript=
function Row({ title, fetchUrl, isLargeRow = false }) {
const [movies, setMovies] = useState([]);
const base_url = "https://image.tmdb.org/t/p/original/";
useEffect(() => {
async function fetchData() {
const request = await axios.get(fetchUrl);
setMovies(request.data.results);
return request;
}
fetchData();
}, [fetchUrl]);
return (
<div className="row">
<h2>{title}</h2>
<div className="row__posters">
{movies.map(
(movie) =>
((isLargeRow && movie.poster_path) ||
(!isLargeRow && movie.backdrop_path)) && (
<img
className={`row__poster ${isLargeRow && "row__posterLarge"}`}
key={movie.id}
src={`${base_url}${
isLargeRow ? movie.poster_path : movie.backdrop_path
}`}
alt={movie.name}
/>
)
)}
</div>
</div>
);
}
```
在css的小技巧裡,讓不想要有滾動條可以在css裡這樣設置
```javascript=
.row__posters {
display: flex;
overflow-y: hidden;
overflow-x: scroll;
padding: 20px;
}
.row__posters::-webkit-scrollbar {
display: none;
}
```