深入理解 useImperativeHandle
前言
useImperativeHandle 大概是 React 中最冷門的其中一個 Hook,我自己在學習 React 的前兩年幾乎沒用過。直到最近在實作一個「字幕跟隨影片進度」的功能時,我需要讓父層元件能夠控制子層播放器元件的影片進度,才使用到這個 Hook。研究之後發現它其實解決了一個很特定但很實用的問題:如何讓父元件以「命令式」的方式操作子元件。這篇文章整理了我對 useImperativeHandle 的理解,希望能幫助讀者在遇到類似需求時知道該怎麼處理。
什麼是 Imperative(命令式)?
在深入 useImperativeHandle 之前,先來理解什麼是「命令式」和「宣告式」的差別,這對理解這個 Hook 的定位很重要。
宣告式 vs 命令式
讓我們先用一個生活化的例 子來理解這兩種程式設計風格的差異:
情境:你想要一杯咖啡
// 命令式 (Imperative):你告訴咖啡師「每一步該怎麼做」
1. 拿一個杯子
2. 磨 20 克咖啡豆
3. 將水加熱到 92 度
4. 把熱水倒入濾杯
5. 等待 3 分鐘
6. 把咖啡倒入杯子
// 宣告式 (Declarative):你只告訴咖啡師「你要什麼」
「我要一杯美式咖啡」
- 命令式:描述「如何做」(How)—— 一步一步告訴電腦該執行什麼操作
- 宣告式:描述「要什麼」(What)—— 只說明最終想要的結果,讓系統自己決定怎麼達成
再來看一個程式碼的例子,假設我們要把陣列中的每個數字乘以 2:
const numbers = [1, 2, 3, 4, 5];
// 命令式:告訴電腦「每一步該怎麼做」
const doubled1 = [];
for (let i = 0; i < numbers.length; i++) {
doubled1.push(numbers[i] * 2);
}
// 宣告式:告訴電腦「我要什麼結果」
const doubled2 = numbers.map(n => n * 2);