useImperativeHandle 鉤子函數(shù)

Reat 中的 useImperativeHandle 鉤子函數(shù)

通過例子說明 ref 的不足

當(dāng)我們需要調(diào)用子組件中的方法時,我們都是考慮使用useRef來調(diào)用子組件的方法,具體的示例代碼如下:

// 父級組件
const UseImperativeHandleDemo: React.FC = () => {
  const inputRef = useRef<HTMLInputElement>(null);

  return (
    <div>
      <CustInput ref={inputRef} initVal={"123"} />
      <button onClick={() => inputRef.current?.focus()}>獲取焦點(diǎn)</button>
    </div>
  );
};

// CustInput子組件
const CustInput = React.forwardRef<HTMLInputElement, CustInputProp>(
  (
    props: CustInputProp,
    ref: React.ForwardedRef<HTMLInputElement>
  ): JSX.Element => {
    return <input ref={ref} value={props.initVal} onChange={() => {}} />;
  }
);

這個例子中我們只是將一個引用直接傳遞給組件內(nèi)部的單個元素,那是沒有問題的,假如我們需要功能做的更加復(fù)雜一點(diǎn)或者需要自定義引用時,代碼開發(fā)難度可能就會大大提升。

在上述例子中使用 useImperativeHandle 鉤子函數(shù)擴(kuò)展自定義函數(shù)

我們在上述例子的基礎(chǔ)上使用useImperativeHandle鉤子函數(shù)進(jìn)行自定義函數(shù)的擴(kuò)展,擴(kuò)展后我們就可以在父級組件調(diào)用子組件的方法。

使用useImperativeHandle鉤子函數(shù)后我們就可以在子組件中隨意定義方法對外暴露方法。具體的實(shí)例如下:

const CustInput = React.forwardRef<any, CustInputProp>(
  (props: CustInputProp, ref: React.ForwardedRef<any>): JSX.Element => {
    useImperativeHandle(
      ref,
      () => {
        return { alertHi: () => alert(props.initVal) };
      },
      []
    );

    return <input value={props.initVal} onChange={() => {}} />;
  }
);

// 父組件
<button
  onClick={() => {
    inputRef.current?.alertHi(); // 調(diào)用子組件自定義的方法
  }}
>
  獲取焦點(diǎn)
</button>;

使用 useImperativeHandle 鉤子函數(shù)控制子組件中的多個元素

在上一小節(jié)我們簡單實(shí)用了useImperativeHandle鉤子函數(shù)進(jìn)行了子組件自定義函數(shù)的擴(kuò)展,在本小節(jié)中,我們可以使用useImperativeHandle鉤子函數(shù)實(shí)現(xiàn)控制子組件中多個元素。

首先我們先看一下我們要實(shí)現(xiàn)的例子,具體界面如下:

[圖片上傳失敗...(image-778d3d-1711673308562)]

在上述的頁面中,我們的業(yè)務(wù)需求是讓上述對應(yīng)的按鈕控制對應(yīng)子組件中對應(yīng)元素的焦點(diǎn),我們可以在父級組件把對應(yīng)的方法編寫好以后傳遞給子組件,但是這樣就會破壞單一職責(zé)原則,所以我們可以使用useImperativeHandle鉤子來實(shí)現(xiàn),具體的代碼如下:

// 父級組件
const [open, setOpen] = useState<boolean>(false)
const modalRef = useRef<any>(null)

 <div>
  <button onClick={() => setOpen(true)}>open</button>
  <button onClick={() => modalRef.current.closeFocus()}>focus close</button>
  <button onClick={() => modalRef.current.confirmFocus()}>focus confirm</button>
  <button onClick={() => modalRef.current.denyFocus()}>focus deny</button>
  <ConfirmationModal
    ref={modalRef}
    isOpen={open}
    onClocse={() => setOpen(false)}
  />
</div>

// 子組件
const ConfirmationModal = React.forwardRef<any, ConfirmationModalProps>(
  ({ isOpen, onClocse }: ConfirmationModalProps, ref: React.ForwardedRef<any>): JSX.Element => {
    const closeRef = useRef<HTMLButtonElement>(null)
    const confirmRef = useRef<HTMLButtonElement>(null)
    const denyRef = useRef<HTMLButtonElement>(null)

    useImperativeHandle(ref, () => {
      return {
        closeFocus: () => closeRef.current?.focus(),
        confirmFocus: () => confirmRef.current?.focus(),
        denyFocus: () => denyRef.current?.focus()
      }
    }, [])

    if (!isOpen) return <></>

    return (
      <div className="modal">
        <button className="close-btn" ref={closeRef} onClick={(e) => onClocse()}>&times;</button>
        <div className="modal-header">
          <h1>title</h1>
        </div>
        <div className="modal-body">
          do yo confirm?
        </div>
        <div className="modal-footer">
          <button className="confirm-btn" ref={confirmRef} onClick={() => onClocse()}>Yes</button>
          <button className="deny-btn" ref={denyRef} onClick={() => onClocse()}>No</button>
        </div>
      </div>
    )
  }
)

總結(jié)

通過上述兩個簡單的例子,我們可以看到useImperativeHandle的鉤子函數(shù)主要是簡化我們對子組件的控制,即可以在子組件中實(shí)現(xiàn)自定義函數(shù)和控制子組件中的元素。這就是useImperativeHandle鉤子函數(shù)的作用。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容