今天讀了官方文件 Ref 相關的二篇文章,內容是 Referencing 和透過 Ref 操作 DOM,來透過實作練習看看。
目前有二個檔案一個是 App.js 另一個是 VideoPlayer 的元件。
import React from "react";
import VideoPlayer from "./VideoPlayer";
function App() {
return (
<main>
<VideoPlayer
src="https://sandpack-bundler.vercel.app/videos/snowstorm.mp4"
caption="Snow falls by a pine tree and house"
/>
<dl>
<dt>Filmed by</dt>
<dd>Karolina Grabowska</dd>
<dt>Licensed under</dt>
<dd>Creative Commons Zero (CC0)</dd>
</dl>
</main>
);
}
export default App;
import React from "react";
function VideoPlayer({ src, caption }) {
const playbackRateSelectId = React.useId();
return (
<div className="video-player">
<figure>
<video controls src={src} />
<figcaption>{caption}</figcaption>
</figure>
<div className="actions">
<label htmlFor={playbackRateSelectId}>Select playback speed:</label>
<select id={playbackRateSelectId} defaultValue="1">
<option value="0.5">0.5</option>
<option value="1">1</option>
<option value="1.25">1.25</option>
<option value="1.5">1.5</option>
<option value="2">2</option>
<option value="3">3</option>
</select>
</div>
</div>
);
}
export default VideoPlayer;
畫面看起來是這樣子:
透過下拉式選單來選擇播放速度。
設定事件,使用onChange
這個步驟在之前的練習都有練習過。
<select
id={playbackRateSelectId}
defaultValue="1"
onChange={event=>{
event.target.value
}}
>
在此event.target.value
的值就會是option
裡面的播放速度
<option value="0.5">0.5</option>
<option value="1">1</option>
<option value="1.25">1.25</option>
<option value="1.5">1.5</option>
<option value="2">2</option>
<option value="3">3</option>
接著按照 React 官方文件教我們的步驟**Manipulating the DOM with a ref**在VideoPlayer
元件當中宣告 Ref 變數。
const videoRef = useRef();
Ref 是一個一個 JavaScript Object,在這邊因為還沒有給它任何值所以預設會是一個內含 undefined 的 object。印出來會是這樣子的結果:
繼續參照步驟,將剛剛設定為變數的 Ref 透過 ref attribute 傳遞給 JSX tag。
<video ref={videoRef} controls src={src} />
像這樣在我們要傳遞資料的 tag <video>
上設置 ref。
補充:雖然在這邊我們可以在 tag 上直接設定 ref,但如果是自定義的元件的的話,則無法這麼做,需要透過React.forwardRef()
來處理。見此說明。
當處理好這個步驟,此時的 ref object 印出來會是這樣的結果,因為我們已經將 ref 設定在 video 上了。
因為設定好 ref 的資料傳遞,我們現在可以在需要動作的地方onChange
使用它:
<select
id={playbackRateSelectId}
defaultValue="1"
onChange={event=>{
videoRef.current.playbackRate = event.target.value
}}
>
這樣我們就完成這加快影片播放速度的功能了。
以上也就是 ref 的基本操作。
透過實作大致理解 ref 的操作了,那我們又該如何去理解 ref 呢?我們可以理解 Ref 就像是一個盒子或是一個口袋,可以脫離 react 世界的規則。和 useState
不同,useRef
的改變不會引起元件的重新渲染。也就是說,當你只想儲存一個值,而不希望元件因此重新渲染時,使用 useRef 便是一個不錯的選擇。另外,雖然這次沒有操作到,但 Ref 的初始值不一定要是 null,也可以是其他的 JavaScript 的任何值,如物件、數字、字串。官方文件另外有提供一個refs 和 state 的比較表也可以參考看看。
(本篇練習內容出自The Joy of React當中的練習題。)