使用函數(shù)時組件的時候,ref轉發(fā)是必須要了解的概念
// 實現(xiàn) ref 的轉發(fā)
const FancyInput = React.forwardRef((props, ref) => (
<div>
<input ref={ref} type="text" />
<div>我是自定義的函數(shù)式組件</div>
</div>
));
const App = () => {
const ref = useRef();
return (
<div>
<FancyInput ref={ref} />
<button onClick={() => {ref.current.focus()}}>
調用input的focus方法
</button>
</div>
)
}
ReactDOM.render(<App />, root);
如上,簡介明了的解釋了ref轉發(fā)的概念。
但是仍律,上面的 ref 透傳的方式有什么問題呢
站在
FancyInput
組件的角度,FancyInput
組件在中間層水泉,父組件App
越過了自己钢拧,直接獲取了自己的子組件input
的ref
畔师,子組件的DOM直接暴露給了父組件input
組件的所有方法都直接暴露給App
看锉,App組件可以進行任意的操作伯铣,某些情況的不可控我們只是希望
App
可以操作的input
的focus
方法,并不希望它隨意操作其他方法
useImperativeHandle
就是來解決這個問題的:
const FancyInput = React.forwardRef((props, ref) => {
const inputRef = useRef();
useImperativeHandle(ref, () => ({
focus: () => {
// 這里可以加自己的邏輯哦
inputRef.current.focus();
}
}));
return (
<div>
<input ref={inputRef} type="text" />
<div>我是自定義的函數(shù)式組件</div>
</div>
)
});
const App = props => {
const fancyInputRef = useRef();
return (
<div>
<FancyInput ref={fancyInputRef} />
<button onClick={() => {fancyInputRef.current.focus()}}>
調用FancyInput組件的 focus方法
</button>
</div>
)
}
ReactDOM.render(<App />, root);
使用 useImperativeHandle
后,FancyInput
有自己的 ref,通過 React.forwardRef 將父組件的 ref 透傳過來撩扒,通過 useImperativeHandle
方法來暴露指定的方法給父組件調用,完美的解決了上面的問題炒辉。你還可以自己在 input 的 focus 方法上加一些自己的邏輯或者副作用泉手,是不是有點鉤子的意味了。
注意: useImperativeHandle 和 React.forwardRef 必須是配合使用的啡氢。