S
Shih, Cheng-Fu8 個月前

關於useImperativeHandle


在 React 中,管理組件實例和它們的內部狀態有時可能相當複雜,特別是當你需要更多對組件的控制時。useImperativeHandle提供了一種方法,通過 ref 從子組件向父組件暴露特定的實例值或一組函數。

基本語法如下:

useImperativeHandle(ref, createHandle, [deps]);
  • ref: 這是從父組件傳遞的 ref。
  • createHandle: 函數返回你想要暴露的值或函數的對象。
  • deps: 依賴數組,如果有變化,會更新暴露的函數。

實際應用

1.暴露自定義方法

假設你有一個自定義輸入組件,希望父組件在點擊按鈕時能夠聚焦此輸入框。通常情況下,內部輸入元素的 DOM 對父組件是隱藏的。使用useImperativeHandle,你可以輕鬆創建並暴露自定義聚焦方法。

例如:

子組件:

import React, { forwardRef, useRef, useImperativeHandle } from 'react';

const FancyInput = forwardRef((props, ref) => {
  const inputRef = useRef();
  useImperativeHandle(ref, () => ({
    focus: () => {
      inputRef.current.focus();
    }
  }));

  return <input ref={inputRef} {...props} />;
});

父組件:

import React, { useRef } from 'react';
import FancyInput from './FancyInput';

function App() {
  const inputRef = useRef();

  return (
    <>
      <FancyInput ref={inputRef} />
      <button onClick={() => inputRef.current.focus()}>
        Focus the input
      </button>
    </>
  );
}

在這個例子中,FancyInput 組件使用useImperativeHandle 向任何使用 ref 與FancyInput 互動的父組件暴露focus 方法。

2.管理媒體播放

對於一個媒體播放器組件,你可以暴露如播放(play)、暫停(pause)或重置(reset)等方法。

子組件:

const MediaPlayer = forwardRef((props, ref) => {
  const audioRef = useRef();
  useImperativeHandle(ref, () => ({
    play: () => {
      audioRef.current.play();
    },
    pause: () => {
      audioRef.current.pause();
    },
    reset: () => {
      audioRef.current.currentTime = 0;
    }
  }));

  return <audio ref={audioRef} src={props.src} controls />;
});

父組件:

import React, { useRef } from 'react';
import MediaPlayer from './MediaPlayer';

function App() {
  const mediaRef = useRef();

  return (
    <>
      <MediaPlayer ref={mediaRef} src="example.mp3" />
      <button onClick={() => mediaRef.current.play()}>
        Play
      </button>
      <button onClick={() => mediaRef.current.pause()}>
        Pause
      </button>
      <button onClick={() => mediaRef.current.reset()}>
        Reset
      </button>
    </>
  );
}

在此例中,MediaPlayer 組件使用useImperativeHandle 向任何使用 ref 與MediaPlayer 互動的父組件暴露控制媒體播放的方法。父組件提供了播放、暫停和重置的按鈕。

使用時機

useImperativeHandle 應謹慎使用。React 的聲明式特性應始終是你的首選工具。當你絕對需要以一種無法通過 props 或狀態進行的方式與子組件互動時,再考慮使用useImperativeHandle。例如,當與第三方 DOM 庫集成或管理焦點、選擇或動畫時。

總結

useImperativeHandle 提供了一種強大的方式來與子組件進行互動。通過暴露子組件的特定功能,你可以保持組件間清晰且可管理的接口,增強代碼的可擴展性和可讀性。關鍵是適度使用它來補充 React 的聲明式本質,而不是替代它。


其他關於hook系列文章:

關於useDeferredValue 關於useImperativeHandle 關於useSyncExternalStore 關於useTransition


圖片
圖片
圖片
圖片
圖片
圖片
(使用 Facebook 留言外掛程式 留言無法滿足本網站參加活動之資格,僅供非會員討論使用)
互動地圖
interactive taiwan map