起こった問題
React18にあるローディングを簡単にする機能、Suspenseにおいて、よくわからない事象が起きた。
簡潔に言うと、SSRとCSRで生成されたDOM情報が異なるというエラーだ。
Error: Text content does not match server-rendered HTML
Error: There was an error while hydrating this Suspense boundary. Switched to client rendering.
なぜ起こるのか
fetchなど、APIを用いてデータを取得している画面でデータを更新、リロードを行うと、SSRはキャッシュがあるためか、はたまたバグか、データ更新前の情報を保持している。
その後、CSRはAPIで最新のデータを取得しレンダリングする。
その結果、更新前と更新後で情報が異なるため、レンダリングされた情報が異なるとエラーになる。
解決方法
remix-utilsモジュールを利用しました。
この中にある、ClientOnly
を用いると、レンダリングをクライアントだけにできます。
使い方はシンプルで、SuspenseのかわりにClientOnlyタグに変更し、子要素を{}でreturnするように修正します。
$ npm i remix-utils
import { ClientOnly } from "remix-utils/client-only";
{中略}
// Suspense → ClientOnly
// <Suspense fallback={<Loading />}>{child}</Suspense>
<ClientOnly fallback={<Loading />}>{() => <>{child}</>}</ClientOnly>
まとめ
- React18のSuspenseとfetchを使用した際に起こるエラーと解決方法について
- ClientOnlyをつかって、レンダリングをCSRのみに
- エラーはReact側のバグの可能性があるため、アップデートで治るかも
参考
How to troubleshoot hydrating errors? · remix-run/remix · Discussion #5648
Hello, My app is spitting hydration errors every second. I have 2.5K errors per hour. These are the error types: There w...
コメント