React.forwardRef
使得父組件能夠操作子組件的ref
1、子組件
const 子組件 = React.forwardRef((props, ref) => {
return(
<div>
<input ref={ref} type="text" />
<button>{props.children}</button>
</div>
)
});
2、父組件
將父組件的ref綁定到子組件上就可操控子組件,ref.current.xxx
function App() {
const ref = useRef();
return (
<div>
<子組件 ref={ref}>Click Me</子組件>
</div>
)
}
ImperativeHandleHook
當使用React.forwardRef時,父組件的ref和子組件的ref都是同一個ref
當使用ImperativeHandleHook,可以使得父組件和子組件擁有各自的ref,並且子組件可選擇性地暴露其他內容
1、子組件
const 子組件= React.forwardRef((props, ref) => {
const inputRef = useRef();
useImperativeHandle(ref, () =>{
return{ 暴露給父組件的ref的值
focus: () => {
inputRef.current.focus();
},
其他內容...
}
});
return <input ref={inputRef} type="text" />
});
2、父組件
將父組件的ref綁定到子組件上,就可獲取子組件通過ref暴露的內容,父組件Ref.current.子組件暴露的內容
const App = props => {
const 父組件Ref = useRef();
return (
<div>
<子組件 ref={fancyInputRef} />
<button
onClick={() => fancyInputRef.current.focus()}
>父組件調用子組件的 focus</button>
</div>
)
}
代碼示例:
React.forwardRef:
import React, { useCallback, useRef } from 'react';
import ReactDOM from 'react-dom';
// 實現 ref 的轉發
const FancyButton = React.forwardRef((props, ref) => (
<div>
<input ref={ref} type="text" />
<button>{props.children}</button>
</div>
));
// 父組件中使用子組件的 ref
function App() {
const ref = useRef();
const handleClick = useCallback(() => ref.current.focus(), [ ref ]);
return (
<div>
<FancyButton ref={ref}>Click Me</FancyButton>
<button onClick={handleClick}>獲取焦點</button>
</div>
)
}
ReactDOM.render(<App />, root);
ImperativeHandleHook:
import React, { useRef, useImperativeHandle } from 'react';
import ReactDOM from 'react-dom';
const FancyInput = React.forwardRef((props, ref) => {
const inputRef = useRef();
useImperativeHandle(ref, () => ({
focus: () => {
inputRef.current.focus();
}
}));
return <input ref={inputRef} type="text" />
});
const App = props => {
const fancyInputRef = useRef();
return (
<div>
<FancyInput ref={fancyInputRef} />
<button
onClick={() => fancyInputRef.current.focus()}
>父組件調用子組件的 focus</button>
</div>
)
}
ReactDOM.render(<App />, root);