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;

輸出

counter

示例 - 公開我們自己的指令式方法

在一個元件中,我們可以建立我們自己的自定義方法並將其提供給其父元件。這些自定義方法不必與 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。

reactjs_reference_api.htm
廣告
© . All rights reserved.