React-[useEffect篇]- 如何選擇一個項目並且切換畫面


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]);







你可能感興趣的文章

JavaScript 核心 - Event Loop

JavaScript 核心 - Event Loop

[ 筆記 ] JavaScript 進階 07 - Prototype Chain

[ 筆記 ] JavaScript 進階 07 - Prototype Chain

Android Chip 實作紀錄

Android Chip 實作紀錄






留言討論