Я пытаюсь включить динамический импорт в своем приложении React. Большинство примеров React отображает приложение для некоторого тега, заменяющего контент, например:
ReactDOM.render(<App />, document.getElementById('app'));
Но мне нужно сохранить статический блок внутри элемента #app и отобразить React следующим образом:
let container = document.createElement('div');
ReactDOM.render(<App />, container);
let app = document.getElementById('app');
app.appendChild(container);
let renderedHeader = container.querySelector('#header');
let renderedWrapper = container.querySelector('#wrapper');
app.querySelector('#header').replaceWith(renderedHeader);
app.querySelector('#wrapper').replaceWith(renderedWrapper);
Все работает так, как ожидалось, пока я не попробую использовать компоненты lazy / Suspense.
Вот (Суть / Stackblitz) полный пример, который бросает
DOMException: Failed to execute 'removeChild' on 'Node': The node to be removed is not a child of this node. внутри компонента Suspense.
Это моя проблема или проблема с задержкой?
Есть ли более распространенный способ визуализации приложения React, но с сохранением статических блоков?
Он должен быть достигнут на сервере в статическом файле устаревшими приложениями.
Что ты имеешь в виду? Содержимое статического объекта извлекается с сервера? Если это так, используйте dangerouslySetInnerHTML для загрузки данных в ваш компонент после его загрузки.
@MatthewHerbst Да, именно так
Нет, я не могу установить HTML в приложении React, мне нужно, чтобы он был там до React, так как устаревшее приложение не поддерживает javascript
Подумайте о предоставлении работоспособной демонстрации, которую можно хотя бы отладить. Кроме того, демонстрация, размещенная на Stackblitz или другом сервисе, имеет больше шансов выжить с течением времени, чем ваша собственная суть.
Извините, у меня нет опыта работы со Stackblitz или "другим сервисом", попробую его настроить.
@estus добавил ссылку на stackblitz
Я понимаю. Это не проблема с задержкой, вам просто не нужно изменять DOM вручную. Селекторы #header и т. д. Относятся к разным элементам в разные моменты времени. Я не уверен, как именно нужно реорганизовать код в вашем случае, но это обычное применение для порталов. См., Например, stackoverflow.com/questions/53557119/… или stackoverflow.com/a/52408076/3731501.



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Проблема здесь в том, что селекторы #header и #wrapper ссылаются на разные элементы в разные моменты времени.
В момент выполнения container.querySelector('#header')#header ссылается на <div id = "header"> в резервном компоненте (LoadingView), который предполагается удалить из DOM позже.
Предпочтительно рассматривать Header и Wrapper как разные компоненты и монтировать их в существующие заполнители <div id = "header"> и <div id = "wrapper"> как порталы. Они по-прежнему могут быть вложены в родительский компонент (App или Main) для совместного использования состояния между ними.
Интересный. Но createPortal добавляет компонент к #header как дочерний и не удаляет его старое содержимое. Я что-то скучаю?
Если это единственное препятствие, вы можете заранее очистить содержимое #header, чтобы удалить материал Header template.
Если я делаю document.getelementbyid('header').innerHTML='', я получаю то же исключение DOM, что и раньше
Вы делаете это с порталами? Можете ли вы предоставить демонстрацию того, как вы это делаете?
Решена проблема, не предоставляя заголовок в загружаемом компоненте, который мне не нужен для обновления заголовка в режиме загрузки.
Да, это идея. Проблема заключалась в том, что вы очистили содержимое #header, где портал заголовка уже отображался. Поскольку Header не должен знать, что это портал, вы можете переместить ReactDOM.createPortal и innerHTML в Main.
Почему статический элемент не может быть просто еще одним компонентом React? Это был бы идеальный способ (не знаю, решит ли он вашу проблему)