react material ui Рендер компонента в строку ломает CSS

Ситуация

У нас есть блок, котором работает JS не зависимый от реакта (напр. карта), мы хотим отредндерить какой-то компонент в HTML, чтобы потом показать его во всплывающей подсказке на карте

В коде это может выглядеть как-то так:

import { renderToString } from 'react-dom/server';

// рендерим его
let html =  renderToString(<MapTooltip />); 

mapTooltip
  .setHTML(html) // используем в не-реакт вызове
  .addTo(map);

Проблема в Material Ui

Если то, что вы рендерите, как-то завязано на использование темы (системы стилизации) Material Ui, то вызов renderToString() на клиенте через систему темизации Матириала добавит новые стили, их имена могу (считайте- сопадут) совпасть с теми, что вы используете в основном приложении, но т.к. мы проводим рендеринг без ThemeProvider, то эти стили будут стилями по-умолчанию, что сломает вашу верстку.

Варианты решения

1. Рендерить используя ThemeProvider

Рендерить используя ThemeProvider, причем передавать нужно ту же тему, что вы создали в основном приложении

Плюсы подхода: используйте все возможности Материала
Минусы подхода: с каждым вызовом renderToString() будет происходить дублирование CSS (дублировать будут все те же стили, но все равно это не очень хорошо) + такой подход может быть затратным по ресурсам

2. Отказать в renderToString() от всех зависимостей от Material Ui

Это более экономный по ресурсам вариант + более изящный.

Как его реализовать:

  1. В аргументе ( в примере выше то MapTooltip) откажитесь от любых вызовов связанных с работой CSS через Матириал, напр. не вызывайте useStyles()
  2. Получайте имена классов для MapTooltip (напр. через useStyles()) как пропсы этого компонента MapTooltip, для этого вызовете useStyles() в том компоненте, что делает вызов renderToString() и является обычным реактовским.

    Таким образом вы не будете генерировать стили заново на каждый вызов renderToString(), а просто получите имена классов как пропсы-строки и подставите их. Генерация html, таким образом вообще не будет влиять на систему работы с CSS material UI

Ссылки "по теме":

  1. Похожий пример рендера с ThemeProvider: https://stackoverflow.com/a/47491794
  2. Просто связанное, для экспериментов с вложениями --Theme nesting with Material UI: https://stackoverflow.com/questions/5694...
vedro-compota's picture

_____________
матфак вгу и остальная классика =)