Working with portals in Next JS
Working on a modal component for Windmill React UI, I found a problem while trying to render my component with Next.js. I don't recall the exact error message, but was something along the lines of 'document is not defined'. The typical error when you're trying to use something that is DOM exclusive while still in the server, like document
or window
.
I tried following the with-portals
example on Next's repo, but it would give me this error: 'Target container is not a DOM element.'
Inspecting it, I found that the ref
wasn't being updated and it would return always null
. More investigation could find the issue, but I found another way of making it work without depending on a new component (my case is simple so I don't see a problem for the solution living inside the only place that needs it).
import { createPortal } from 'react-dom'
...
const [mounted, setMounted] = useState(false)
useEffect(() => {
setMounted(true)
}, [])
const modalComponent = <span>the component to be rendered using the Portal</span>
return mounted ? createPortal(modalComponent, document.body) : null
...
It's that simple. The []
inside the useEffect
will make sure that this only run on mount, so as soon as it is mounted, the mounted
state is updated and the portal is created. It fixes the problem because useEffect
is only triggered on client.
Client mounts won't be affected while server is fixed.