React usePortal钩子
创建一个portal,允许在父组件之外渲染子组件。
- 使用
useState()
钩子创建一个状态变量,用于保存portal的render()
和remove()
函数。 - 使用
ReactDOM.createPortal()
和ReactDOM.unmountComponentAtNode()
创建一个portal和一个用于移除portal的函数。使用useCallback()
钩子将这些函数包装和记忆为createPortal()
。 - 使用
useEffect()
钩子在el
的值发生变化时调用createPortal()
并更新状态变量。 - 最后,返回状态变量的
render()
函数。
const usePortal = el => {
const [portal, setPortal] = React.useState({
render: () => null,
remove: () => null,
});
const createPortal = React.useCallback(el => {
const Portal = ({ children }) => ReactDOM.createPortal(children, el);
const remove = () => ReactDOM.unmountComponentAtNode(el);
return { render: Portal, remove };
}, []);
React.useEffect(() => {
if (el) portal.remove();
const newPortal = createPortal(el);
setPortal(newPortal);
return () => newPortal.remove(el);
}, [el]);
return portal.render;
};
const App = () => {
const Portal = usePortal(document.querySelector('title'));
return (
<p>
Hello world!
<Portal>Portalized Title</Portal>
</p>
);
};
ReactDOM.createRoot(document.getElementById('root')).render(
<App />
);