Как исправить ошибку dangerouslySetInnerHTML в Next.js


Введение

В процессе разработки на Next.js 14 я столкнулся с неочевидной проблемой гидратации при использовании dangerouslySetInnerHTML. В этой статье заметке я разберу причины возникновения ошибки и покажу решение, к которому я пришёл во время отладки.

Симптомы проблемы

При использовании dangerouslySetInnerHTML в Next.js 14 у меня возникли две ошибки в консоли:

Ошибка Next.js: «Prop `dangerouslySetInnerHTML` did not match»

Первая ошибка указывает на несоответствие контента между серверным и клиентским рендерингом в dangerouslySetInnerHTML.

Ошибка Next.js: «Hydration failed because the initial UI does not match»

Вторая ошибка сигнализирует о проблеме гидратации из-за несоответствия между серверным и клиентским UI.

При проверке Chrome DevTools можно заметить, что HTML-документ от сервера содержит идентичный текст тому, который отображается после гидратации на клиенте. Это делает ошибку достаточно странной для восприятия.

Проблемный код

Ошибка возникала в следующем фрагменте кода:

<p dangerouslySetInnerHTML={{ __html: text }} />

Где text представляет собой HTML-строку, типичную для WYSIWYG-редакторов.

Причина возникновения ошибок

Корень проблемы кроется в спецификации HTML. В переменной text могут содержаться теги <p>, которые мы пытаемся обернуть в родительский тег <p>.

Согласно спецификации HTML, элемент <p> имеет Phrasing content model, и сам тег <p> не входит в эту модель контента - см. спецификация. Это означает, что вложение параграфов друг в друга недопустимо по стандарту HTML.

Решение проблемы

Исправить ошибку можно простой заменой тега-обёртки на более подходящий (в моём случае <div>):

<div dangerouslySetInnerHTML={{ __html: text }} />

Заключение

Формулировка ошибки, которую видно в Next.js на самом деле сбивает с толку, потому как ошибка “нарушение вложенности тегов” сюда подходила бы лучше и не заставила бы тратить время впустую на понимание причин.

© 2025 Рассудихин Алекс