React18にアップデートしてアプリケーションを起動したところ以下のエラーが表示されるようになった。

Error: Hydration failed because the initial UI does not match what was rendered on the server.

環境

  • React 18.1.0
  • Next.js 12.1.6

エラー内容

Error: Hydration failed because the initial UI does not match what was rendered on the server.

直訳すると、「初期UIがサーバーでレンダリングされたものと一致しないため、ハイドレーションが失敗しました。」

While rendering your application, there was a difference between the React tree that was pre-rendered (SSR/SSG) and the React tree that rendered during the first render in the Browser. The first render is called Hydration which is a feature of React.
This can cause the React tree to be out of sync with the DOM and result in unexpected content/attributes being present.

React Hydration Error

事前(SSRまたはSSG)にレンダリングされたReactツリーと、ブラウザで最初にレンダリングされたReactツリーが異なっているからだそう。
結果、ReactツリーがDOMと同期しなくなるので予期しないコンテンツが存在してしまう恐れがあるとのこと。

原因

現在日時のエポックミリ秒を返却するコードをサンプルとして説明する。

import React, {useState} from 'react';

export const Index = () => {
    // 事前レンダリング時の日時とブラウザでレンダリング日時が不一致となる。
    const [nowDate, setNowDate] = useState(Date.now);
    return nowDate;
}

export default Index;

対処

useEffectを利用して不一致を回避する。

import React, {useEffect, useState} from 'react';

export const Index = () => {
    // 事前レンダリング時の日時とブラウザでレンダリング日時を一致させる。
    const [nowDate, setNowDate] = useState(0);

    // useEffectを使いハイドレーション後にレンダリングがトリガーされるようにする。
    useEffect(() => {
        setNowDate(Date.now);
    }, []);

    return nowDate;
}

export default Index;

Next.jsの公式のsolution内容とほぼ同じ。
React Hydration Error