#reactjs #next.js #emotion #emotion-js
Вопрос:
Текущее поведение:
При наличии стиля, который условно применяется в браузере, стили с сервера не изменяются, даже если компонент запускается и реквизиты браузера передаются правильно. HTML, отправленный обратно с сервера, остается на странице, и даже после первого рендеринга на клиенте, где передаются новые реквизиты на основе браузера, компонент продолжает отображать стили сервера. Это в приложении nextjs, использующем эмоцию 11
Я чувствую, что это должно быть где-то рассмотрено, но я прочесал ТАК, эти проблемы и проблемы nextjs весь день и не нашел ничего, описывающего точную проблему или ее решение.
Для воспроизведения: Codesandbox, показывающий компонент, который имеет один набор стилей на сервере, а затем, когда он находится в браузере, должен переключиться на другой набор стилей
https://codesandbox.io/s/cool-worker-meil8?file=/package.json:200-335
На сервере поле отображается красным, потому что process.browser имеет значение false. В браузере опора isBrowser верна, поэтому поле должно быть синим после запуска js. Однако, несмотря на то, что журналы консоли показывают, что стилизованный компонент действительно запускался на клиенте с isBrowser true, а цвет фона был установлен как синий, поле остается красным (это не в песочнице, но я нашел единственный способ заставить компонент фактически изменить цвет-это навигация на стороне клиента или какое-то отдельное принудительное обновление состояния, которое повторно отправляет компонент).
Ожидаемое поведение:
Я бы ожидал, что сервер отправит обратно html/стили для серверной версии компонента, а затем, после первого рендеринга на клиенте, компонент должен прочитать стили на основе браузера и обновить их в соответствии со стилями, основанными на реквизитах браузера.
Информация об окружающей среде: Кстати, этот codesandbox был построен с использованием базовой версии nextjs на codesandbox. Я не изменил ничего, кроме добавления эмоций
Вот депы в песочнице:
«@эмоция/реакция»: «11.4.1»
«@эмоции/стиль»: «11.3.0»
«следующий»: «последний»
«реагировать»: «17.0.2»
«react-dom»: «17.0.2»
Ответ №1:
Кажется, что это не проблема, связанная с эмоциями, но на самом деле это связано с тем, что более новые версии react не различают dom при гидратации, а вместо этого сохраняют html, все еще генерируя правильное дерево компонентов (таким образом, запускается js, что приводит меня в замешательство, но dom не согласован, чтобы соответствовать тому, что должно быть показано в дереве компонентов).
В случае, если кто-то еще столкнется с этим, решение состоит в том, чтобы использовать подобный компонент, который отображает один компонент непосредственно на сервере, а затем на клиенте запускает рендеринг, установив состояние isMounted в useLayoutEffect (это не будет выполняться/повторно на сервере), который затем отображает клиентский компонент. Общая идея показана здесь: