コンパイラかく語りき

import { Fun } from 'programming'

【React/Next.js】SSG/SSR 環境で React Portal を利用する方法

React Portal を使うと、コンポーネント構造の制約を受けずに、アプリケーション内の任意の箇所に DOM を挿入することができます。

モーダルの実装などで役に立つかと思います。

ja.reactjs.org

そんな React Portal ですが、Next.js の SSR/SSG を利用したところエラーが出てしまいました。

Portal を利用した処理として document.getElementById を行っているのですが、サーバーサイドでは document にアクセスできないためです。

解決策としては、 useState/useEffect を組み合わせて、クライアント判定することでエラーを回避できました。

import { useEffect, useState } from 'react'
import ReactDOM from 'react-dom'

export const Foo = () => {
  const [isClient, setIsClient] = useState(false);

  useEffect(() => {
    // クライアント判定
    if (typeof window !== undefined) {
      setIsClient(true)
    }
  }, [])

  useEffect(() => {
    if (!isClient) {
      return
    }

    // ここでクライアントサイドで行いたい処理など
    
  }, [isClient])

  if (!isClient) {
    return null
  }

  return ReactDOM.createPortal(
    // 挿入したいコンポーネント
    <SomeComponent>,
    // 挿入先
    document.getElementById('portal-target')
  )
};