[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 了。
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;