Add usePortal

This commit is contained in:
Chalarangelo
2021-11-25 11:01:40 +02:00
parent 4fa76a1a96
commit 8683f4d233
4 changed files with 54 additions and 3 deletions

View File

@ -1,6 +1,6 @@
---
title: useOnGlobalEvent
tags: hooks,effect,intermediate
tags: hooks,effect,event,intermediate
firstSeen: 2021-12-22T05:00:00-04:00
---

View File

@ -1,6 +1,6 @@
---
title: useOnWindowResize
tags: hooks,effect,intermediate
tags: hooks,effect,event,intermediate
firstSeen: 2021-12-01T05:00:00-04:00
---

View File

@ -1,6 +1,6 @@
---
title: useOnWindowScroll
tags: hooks,effect,intermediate
tags: hooks,effect,event,intermediate
firstSeen: 2021-12-08T05:00:00-04:00
---

51
snippets/usePortal.md Normal file
View File

@ -0,0 +1,51 @@
---
title: usePortal
tags: hooks,state,effect,advanced
firstSeen: 2022-01-05T05:00:00-04:00
---
Creates a portal, allowing rendering of children outside the parent component.
- Use the `useState()` hook to create a state varible that holds the `render()` and `remove()` functions for the portal.
- Use `ReactDOM.createPortal()` and `ReactDOM.unmountComponentAtNode()` to create a portal and a function to remove it. Use the `useCallback()` hook to wrap and memoize these functions as `createPortal()`.
- Use the `useEffect()` hook to call `createPortal()` and update the state variable any time `el`'s value changes.
- Finally, return the `render()` function of the state variable.
```jsx
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;
};
```
```jsx
const App = () => {
const Portal = usePortal(document.querySelector('title'));
return (
<p>
Hello world!
<Portal>Portalized Title</Portal>
</p>
);
};
ReactDOM.render(<App />, document.getElementById('root'));
```