跳至主要内容

[react] React useImperativeHandle

程式碼連結

useRef

如果要在 React 使用像是 input focus 的 DOM 方法,可以透過 useRef 來達到以上需求。

App.js
import { useRef } from "react";import "./App.css";function App() {  const inputRef = useRef(null);  const focusInput = () => {    inputRef.current.focus();  };  return (    <div className="App">      <button onClick={focusInput}>Focus</button>      <input type="text" placeholder="type..." ref={inputRef} />    </div>  );}export default App;

但要是今天 input 是被包裝在 Component 內的話,ref 就不會起作用,因為 ref 是綁定在 Component 上,並不是 input jsx。

App.js
import { useRef } from "react";import "./App.css";import Input from "./Input";function App() {  const inputRef = useRef(null);  const focusInput = () => {    inputRef.current.focus();  };  return (    <div className="App">      <button onClick={focusInput}>Focus</button>      <Input ref={inputRef} />    </div>  );}export default App;
Input.js
import React from "react";const Input = () => {  return (    <>      <h2>Input</h2>      <input type="text" placeholder="type..." />    </>  );};export default Input;

forwardRef

而我們可以使用 forwardRef 來取得 Parent Component(App.js)傳遞過來的 ref。

在 Input Component 使用 forwardRef,並將 ref 輸出到 console。

Input.js
import React, { forwardRef } from "react";const Input = forwardRef((props, ref) => {  console.log(ref);  return (    <>      <h2>Input</h2>      <input type="text" placeholder="type..." />    </>  );});export default Input;

可以看到我們成功取得了從 Parent Component 傳遞過來的 ref 了。

Image

useImperativeHandle

接著可以透過 useImperativeHandle 來綁定 function 給 Parent Component 使用。

這邊要注意的是,我們一樣需要在 Input Component 使用 useRef,並將 ref 綁定在 input jsx 標籤上,這樣才能知道待會要 focus 哪一個元素。

Input.js
import React, { useRef, forwardRef, useImperativeHandle } from "react";const Input = forwardRef((props, ref) => {  const inputRef = useRef();  useImperativeHandle(ref, () => ({    focusInput: () => {      inputRef.current.focus();    },  }));  return (    <>      <h2>Input</h2>      <input type="text" placeholder="type..." ref={inputRef} {...props} />    </>  );});export default Input;

綁定完 function 後,現在可以在 Parent Component 去使用 focusInput function 了

App.js
import { useRef } from "react";import "./App.css";import Input from "./Input";function App() {  const inputRef = useRef(null);  //使用Child Component綁定的focusInput function  const focusInput = () => {    inputRef.current.focusInput();  };  return (    <div className="App">      <button onClick={focusInput}>Focus</button>      <Input ref={inputRef} />    </div>  );}export default App;