usePortal
The usePortal
hook provides a way to create a portal in React, allowing you to render children into a DOM node that exists outside the hierarchy of the parent component. This is useful for modals, tooltips, and other UI elements that need to break out of their parent container.
Add the utility
npx @ivnatsr/ezreact add use-portal
import { createPortal } from 'react-dom'import { useState, useLayoutEffect } from 'react'
const isServer = typeof window === 'undefined'
export function usePortal() { const [wrapperElement] = useState(() => { if (isServer) return null return document.createElement('div') })
useLayoutEffect(() => { if (wrapperElement === null) return document.body.appendChild(wrapperElement)
return () => { document.body.removeChild(wrapperElement) } }, [wrapperElement])
return { renderPortal: (children) => { return wrapperElement === null ? null : createPortal(children, wrapperElement) } }}
import { createPortal } from 'react-dom'import { useState, useLayoutEffect, type ReactPortal, type ReactNode } from 'react'
const isServer = typeof window === 'undefined'
export function usePortal() { const [wrapperElement] = useState<HTMLDivElement | null>(() => { if (isServer) return null return document.createElement('div') })
useLayoutEffect(() => { if (wrapperElement === null) return document.body.appendChild(wrapperElement)
return () => { document.body.removeChild(wrapperElement) } }, [wrapperElement])
return { renderPortal: (children: ReactNode): ReactPortal | null => { return wrapperElement === null ? null : createPortal(children, wrapperElement) } }}
Return
This hook returns an object containing the following method:
renderPortal
: A function that takeschildren
as an argument and returns a React portal. If thewrapperElement
isnull
, it returnsnull
.
Example
import { usePortal } from './path/to/use-portal'
const PortalExample = () => { const { renderPortal } = usePortal()
return ( <div> <h1>Main Content</h1> {renderPortal( <div style={{ background: 'lightblue', padding: '20px' }}> This is a portal! </div> )} </div> )}
export default PortalExample