Как включить dom-манипулирующие скрипты в SSR Next. js Приложение - PullRequest
1 голос
/ 19 апреля 2020

Возникает следующая ошибка:

Warning: Text content did not match. Server: "But I want to be altered by the client" Client: "Test"
    in div (at pages/index.tsx:17)
    in div (at pages/index.tsx:6)
    in HomePage (at _app.tsx:5)
    in MyApp
    in Container (created by AppContainer)
    in AppContainer

... со следующей настройкой:

A Далее JS Компонент приложения:

function HomePage() {
  return (
    <>
      <div id="test-div">I am rendered on the server.</div>
      <script src="http://localhost:8080/bundle.js"></script>
    </>
  );
}

export default HomePage;

( Примечание: URL http://localhost:8080/bundle.js предполагает, что webpack-dev-server работает и обслуживает этот ресурс)

Включенный скрипт "example":

const element = document.getElementById('test-div') as any;
element.innerHTML = 'But I want to be altered by the client';

В простой настройке я бы просто файл stati c html, объявляющий элемент div и включающий скрипт "example".

Но я хотел бы использовать Next JS, потому что я хочу рендерить динамич c (SSR ) содержимое страницы (например, текстовое содержимое из cms).

Я заметил, что иногда (если выполнение скрипта занимает больше мс времени), ошибки не возникает. Просто сделайте что-нибудь трудоемкое в примере сценария.

Другой хакерский подход - использовать setTimeout в примере сценария. Я не хочу этого делать, пока не узнаю, почему это происходит:

setTimeout(function() {
  const element = document.getElementById('test-div') as any;
  element.innerHTML = 'But I want to be altered by the client';
}, 20);

1 Ответ

1 голос
/ 19 апреля 2020

Браузер и document, window объекты недоступны во время рендеринга на стороне сервера.

Вы можете инициализировать сценарии, которые манипулируют DOM после монтирования компонента React.

useEffect(() => init(), [])

Чтобы добавить внешний скрипт, вы можете сделать следующее:

useEffect(() => require('../babylon.js'), [])

Чтобы включить скрипт с другого сервера, вы можете добавить тег script:

useEffect(() => {
  const script = document.createElement("script");
  script.src = "http://localhost:8080/bundle.js";
  script.async = true;
  document.body.appendChild(script);
},[])

Если вы добавляете Слушателям DOM вам также необходимо выполнить очистку.

Использование ловушки эффектов

Эффекты с очисткой

...