creat:加入電影到已看過已看過的電影清單
想要實現的畫面是這樣:
+
會需要的資料是:電影海報,電影名,大眾評分,你的評分,電影總長度
想實現的功能:當我們點擊某部電影,會出現該電影的詳細資料之後,會有一段評分的功能,評分後可以有按鈕加入到已看過清單
在元件app上已經有建立已看過電影清單的state:
const [watched, setWatched] = useState([])
在app元件上設計handleAddWatched()函式:
function handleAddWatched(movie) {
setWatched((watched) => [...watched, movie])
}
並且把這個函式作為propsonAddWatched{handleAddWatched}
傳到子元件MovieDetails中:並在這個MovieDetails中加入按鈕元素,並在這個按鈕元素上加入onClick事件,並且在另外MovieDetails內設計函式:
function handleAdd() {
const newWatchedMovie = {
imdbId: selectedId,
title,
year,
poster,
imdbRating: Number(imdbRating),
runtime: Number(runtime.split(" ").at(0))
}
onAddWatched(newWatchedMovie)
}
點擊這個加入到已看過清單的按鈕就會觸發handleAdd()這個函式。
已成功加入已看過清單
點擊加入已看過清單之後,自動關閉detail頁面
先前有寫過一個函式
const handleCloseMovie = () => {
setSelectedId(null);
};
要把這個SelectedId資料清空,detail頁面就會消除
就加入到在MovieDetail這個函式中:
const handleAdd = () => {
const newMovieWatched = {
imdbID: selectedId,
title,
year,
poster,
imdbRating: Number(imdbRating),
runtime: Number(runtime.split(" ").at(0)),
};
onAddWatched(newMovieWatched);
onCloseMovie();
};
我們想要存入使用者對該電影的評分 並顯示在畫面上 -> state
const [userRating, setUserRating] = useState("")
並放入setter fn在startRating的元件中,並把userRating資料也寫在newMovieWatched物件下
const handleAdd = () => {
const newMovieWatched = {
imdbID: selectedId,
title,
year,
poster,
imdbRating: Number(imdbRating),
runtime: Number(runtime.split(" ").at(0)),
userRating
};
onAddWatched(newMovieWatched);
onCloseMovie();
};
並在ui jsx中做畫面判斷,如果有userRating > 0 就顯示加入到已看過清單的按鈕
<div className="rating">
<StarRating
maxRating={10}
size={24}
onSetRating={setUserRating}
/>
{userRating > 0 && (
<button className="btn-add" onClick={handleAdd}>
➕ Add to watched list
</button>
)}
</div>
比對該電影的selectid是不是已經在watched的list中,避免重複加入
就把在app中的state
const [watched, setWatched] = useState([]);
中的watched資料傳遞到MovieDetail元件裡,由於我們是要從現行的state -> watched 去衍生出資料狀態表達傳遞的selectedid是否已存在在watched裡,從watched 中擷取電影的id,再利用.includes()當前的selectedId是否存在來判斷有無重複
const isWatched = watched.map(movie => movie.imdbID).includes(selectId)
再利用這個衍生資料isWatched去判斷ui jsx畫面呈現
<div className="rating">
{!isWatched ? (
<>
<StarRating
maxRating={10}
size={24}
onSetRating={setUserRating}
/>
{userRating > 0 && (
<button className="btn-add" onClick={handleAdd}>
➕ Add to watched list
</button>
)}
</>
) : (
<p>
你已經評分過了<span>⭐️{userRating}</span>
</p>
)}
</div>
在已評分過了加入該電影先前使用者的評分資料
設定衍生資料,
const watchedUserRating = watched.find(movie =>
movie.imdnID === selectedId)?.userRating
刪除已看過清單
在app中設計刪除已看過電影的函式:
function handleDeleteWatched(id) {
setWatched(watched => watched.filter(movie => movie.imdbID !== id))
}
只要是和:你所點擊將要刪除的電影id,不同,這些已看過的電影就留下來
加入刪除按鈕,將handleDeleteWatched點擊事件傳到已看過電影的清單的元件裡,加入onClick事件觸發handleDeleteWatched並傳入點擊刪除的電影id ->資料比對
改變頁面的title
在點擊該電影進入詳細頁面時,想要改變網頁上的title,這個行為是屬於react元件與外部世界的溝通 -> side effect
所以我們要使用useEffect ->
useEffect(() => {
if (!title) return;
document.title = `Movie | ${title}`;
}, [title]);