# 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 ![](https://i.imgur.com/N04XuUF.png) ``` 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; } ```