- ReactJS 教程
- ReactJS - 首頁
- ReactJS - 簡介
- ReactJS - 路線圖
- ReactJS - 安裝
- ReactJS - 特性
- ReactJS - 優點與缺點
- ReactJS - 架構
- ReactJS - 建立 React 應用
- ReactJS - JSX
- ReactJS - 元件
- ReactJS - 巢狀元件
- ReactJS - 使用新建立的元件
- ReactJS - 元件集合
- ReactJS - 樣式
- ReactJS - 屬性 (props)
- ReactJS - 使用屬性建立元件
- ReactJS - props 驗證
- ReactJS - 建構函式
- ReactJS - 元件生命週期
- ReactJS - 事件管理
- ReactJS - 建立一個事件感知元件
- ReactJS - 在 Expense Manager APP 中引入事件
- ReactJS - 狀態管理
- ReactJS - 狀態管理 API
- ReactJS - 無狀態元件
- ReactJS - 使用 React Hooks 進行狀態管理
- ReactJS - 使用 React Hooks 進行元件生命週期管理
- ReactJS - 佈局元件
- ReactJS - 分頁
- ReactJS - Material UI
- ReactJS - Http 客戶端程式設計
- ReactJS - 表單程式設計
- ReactJS - 受控元件
- ReactJS - 非受控元件
- ReactJS - Formik
- ReactJS - 條件渲染
- ReactJS - 列表
- ReactJS - Keys
- ReactJS - 路由
- ReactJS - Redux
- ReactJS - 動畫
- ReactJS - Bootstrap
- ReactJS - Map
- ReactJS - 表格
- ReactJS - 使用 Flux 管理狀態
- ReactJS - 測試
- ReactJS - CLI 命令
- ReactJS - 構建和部署
- ReactJS - 示例
- Hooks
- ReactJS - Hooks 簡介
- ReactJS - 使用 useState
- ReactJS - 使用 useEffect
- ReactJS - 使用 useContext
- ReactJS - 使用 useRef
- ReactJS - 使用 useReducer
- ReactJS - 使用 useCallback
- ReactJS - 使用 useMemo
- ReactJS - 自定義 Hooks
- ReactJS 高階
- ReactJS - 可訪問性
- ReactJS - 程式碼分割
- ReactJS - Context
- ReactJS - 錯誤邊界
- ReactJS - 轉發 Refs
- ReactJS - 片段
- ReactJS - 高階元件
- ReactJS - 與其他庫整合
- ReactJS - 效能最佳化
- ReactJS - Profiler API
- ReactJS - Portals
- ReactJS - 無 ES6 ECMAScript 的 React
- ReactJS - 無 JSX 的 React
- ReactJS - Reconciliation (協調)
- ReactJS - Refs 和 DOM
- ReactJS - Render Props
- ReactJS - 靜態型別檢查
- ReactJS - Strict Mode (嚴格模式)
- ReactJS - Web Components
- 附加概念
- ReactJS - 日期選擇器
- ReactJS - Helmet
- ReactJS - 內聯樣式
- ReactJS - PropTypes
- ReactJS - BrowserRouter
- ReactJS - DOM
- ReactJS - 輪播圖
- ReactJS - 圖示
- ReactJS - 表單元件
- ReactJS - 參考 API
- ReactJS 有用資源
- ReactJS - 快速指南
- ReactJS - 有用資源
- ReactJS - 討論
ReactJS - useImperativeHandle Hook
useImperativeHandle 是 React 18 中引入的一個 React Hook。這個 Hook 允許我們自定義作為子元件 ref 公開的控制代碼。當我們需要立即與子元件連線時,這非常有用,這意味著我們希望立即訪問和呼叫子元件上的方法或屬性。
語法
useImperativeHandle(ref, createHandle, optional_dependency)
引數
ref − 這是一種特殊的工具,可以幫助我們與子元件連線。在使用 forwardRef 建立子元件時,它作為第二個引數接收。
createHandle − 這是關於我們想要對子元件執行的操作的指令集。這是我們從 useImperativeHandle 返回的內容。
可選 _dependencies − 我們需要列出我們在 createHandle 部分中使用的所有內容(例如 props、state 和變數)。這樣 React 就會檢查這些內容,並確保它們不會意外更改。如果它們確實更改了,它將更新我們的特殊工具。
返回值
此方法返回 undefined。
如何使用它?
我們可以在元件的頂層使用 “useImperativeHandle” 來自定義它公開的 ref 控制代碼 −
import { forwardRef, useImperativeHandle } from 'react';
const MyComp = forwardRef(function MyComp(props, ref) {
useImperativeHandle(ref, () => {
return {
// the methods we want in our code ...
};
}, []);
示例
因此,我們可以透過兩種不同的方式使用此 Hook。首先是建立可用於父元件的自定義 ref 控制代碼,其次是公開我們自己的指令式方法。我們將進一步逐一討論這兩種方法。
向父元件提供自定義 ref 控制代碼
預設情況下,React 元件不提供對底層 DOM 元素的直接訪問。我們將不得不使用 forwardRef 來允許父元件訪問子元件中的 <input> DOM 節點。
import { forwardRef } from 'react';
const InputComp = forwardRef(function InputComp(props, ref) {
return <input {...props} ref={ref} />;
});
此程式碼會將實際的 <input> DOM 節點返回給賦予 InputComp 的 ref。
有時我們不想公開完整的 DOM 節點,而只想公開其方法或屬性的一部分。例如,在不公開整個 DOM 節點的情況下聚焦和滾動子元件。我們可以藉助 useImperativeHandle Hook 來自定義公開的控制代碼。
例如
import { forwardRef, useImperativeHandle } from 'react';
const InputComp = forwardRef(function InputComp(props, ref) {
useImperativeHandle(ref, () => ({
focus() {
inputRef.current.focus();
},
scrollIntoView() {
inputRef.current.scrollIntoView();
},
}), []);
return <input {...props} />;
});
在上面的示例中,我們正在修改父元件公開的控制代碼。父元件可以呼叫 InputComp 的 focus 和 scrollIntoView 方法。但它不會直接訪問 DOM 節點 <input>。
示例 - 簡短的應用程式來理解此 Hook
import React, { forwardRef, useImperativeHandle, useRef, useState } from 'react';
const Counter = forwardRef(function Counter(props, ref) {
const [count, setCount] = useState(0);
const increment = () => {
setCount(count + 1);
};
const reset = () => {
setCount(0);
};
useImperativeHandle(ref, () => ({
increment,
reset,
}), []);
return (
<div>
<p>Counter: {count}</p>
</div>
);
});
function App() {
const counterRef = useRef();
const handleIncrement = () => {
counterRef.current.increment();
};
const handleReset = () => {
counterRef.current.reset();
};
return (
<div>
<Counter ref={counterRef} />
<button onClick={handleIncrement}>Increment Count</button>
<button onClick={handleReset}>Reset</button>
</div>
);
}
export default App;
輸出
示例 - 公開我們自己的指令式方法
在一個元件中,我們可以建立我們自己的自定義方法並將其提供給其父元件。這些自定義方法不必與 HTML 元素的內建方法相同。
假設我們有一個 InputForm 元件,它顯示一個簡單的輸入欄位元件 (InputForm),當按下按鈕時,可以將其滾動到檢視中並聚焦。當我們單擊名為 App 的父元件中的按鈕時,將執行輸入欄位上的此方法,使其滾動到檢視中並獲得焦點。
import React, { forwardRef, useRef, useImperativeHandle } from 'react';
const InputForm = forwardRef((props, ref) => {
const inputRef = useRef(null);
useImperativeHandle(ref, () => ({
scrollAndFocus() {
inputRef.current.scrollIntoView();
inputRef.current.focus();
}
}), []);
return <input type="text" ref={inputRef} placeholder="Type here..." />;
});
function App() {
const inputRef = useRef();
const handleButtonClick = () => {
inputRef.current.scrollAndFocus();
};
return (
<div>
<button onClick={handleButtonClick}>Scroll and Focus</button>
<InputForm ref={inputRef} />
</div>
);
}
export default App;
在上面的示例中,我們演示瞭如何使用 forwardRef 和 useImperativeHandle 來滾動和聚焦輸入欄位。
總結
在 18 版中,useImperativeHandle 是一個有用的 React Hook,它允許透過更改 ref 來立即與子元件互動。當我們需要快速訪問子元件的函式或屬性時,它非常有用。透過使用此 Hook,我們可以建立連線並定義我們想要對子元件執行的操作,在需要時提供流暢的通訊和更新,並且該方法返回 undefined。