Задержка реакции компонента на нагрузку до загрузки скрипта головы шлема

У меня есть компонент реагирования, который опирается на Google Maps JS API. Это импортируется в заголовок страницы App.js с тегом script. Когда я пытаюсь загрузить страницу, содержащую этот компонент, происходит сбой, утверждая, что скрипт не загружен. Однако если я сначала открою другую страницу (которая приводит к загрузке сценария, но не включает этот компонент), а затем перейду к странице, содержащей компонент, это работает.

Это наводит меня на мысль, что проблема в том, что скрипт еще не загружен при загрузке компонента. Я думал, однако, что загрузка страницы должна блокироваться, пока она получает скрипт. Я не совсем уверен, как это исправить.

App.js:

class App extends Component {
  render() {
    return (
      <Router>
        <div>
          <Helmet>
            <script
              type="text/javascript"
              src="https://maps.googleapis.com/maps/api/js?key=AIzaSyDSn_vNbNZzrcFxl8bV3MH1j0kuoLVsOCQ&libraries=places"
            />
          </Helmet>

          <div className="pageContent">
                <Route exact path="/foo" component={FooScreen} />
                <Route exact path="/bar" component={BarScreen} /
          </div>
        </div>
      </Router>
    );
  }
}
export default App;

Выше FooScreen содержит компонент, а BarScreen - нет. Если я открою FooScreen напрямую, произойдет сбой, если я открою BarScreen, а затем перейду к FooScreen, он будет работать.

1 ответ

Обычно прослушиватели событий должны быть присоединены к экземпляру элемента скрипта, например, к загрузчику скриптов на основе обещаний.

Этот случай специфичен для Google Maps или других сценариев, которые имеют процедуру асинхронной инициализации и принимают обратный вызов, поэтому слушать излишне load событие:

  state = { mapLoaded: false };

  componentDidMount() {
    window.onGoogleMap = () => this.setState({ mapLoaded: true });
  }

  componentWillUnmount() {
    delete window.onGoogleMap;
  }

  render() {
    return <>
      <Helmet>
        <script
          type="text/javascript"
          src="https://maps.googleapis.com/maps/api/js?key=...&libraries=places&callback=onGoogleMap"
        />
      </Helmet>

      {!this.state.mapLoaded ? (
        'Loading...'
      ) : (
        <Router>...</Router>
      )}
    </>;
  }

Поскольку глобальная переменная используется, для этого требуется не более одного экземпляра App существовать одновременно, включая тесты.

Другие вопросы по тегам