首页 > 解决方案 > react-async-script 实现:包装组件

问题描述

我正在尝试用makeAsyncScriptLoaderfrom包装一个需要 google maps api 的反应组件react-async-script

在同一个文件中(如果有区别的话):

class SearchBar extends Component {
    /* Some stuff requiring the maps api */
}

const callbackName = "onloadcallback";
const URL = `https://maps.googleapis.com/maps/api/js?key=AIzaSyDSn_vNbNZzrcFxl8bV3MH1j0kuoLVsOCQ&callback=${callbackName}`;
const globalName = "foo";

export default makeAsyncScriptLoader(URL, {
  callbackName: callbackName,
  globalName: globalName
})(SearchBar);

我的理解是,然后我应该能够通过SearchBarWrapper从上述文件导入来从另一个文件调用组件,并将其用作<SearchBarWrapper />.

基本上,它不起作用。该组件尝试在没有脚本的情况下加载,但失败了。

标签: reactjsgoogle-mapsgoogle-maps-api-3react-async

解决方案


根据文档,可以指定以下属性以确保 JavaScript 资源已完成加载:

asyncScriptOnLoad: function : 在脚本完成加载后调用。使用 script.onload

或者

callbackName: string : 如果脚本在加载完成时需要调用全局函数(例如:recaptcha/api.js?onload=callbackName)。请在此处提供回调名称,它将在窗口中为您自动注册。

对于 event 的情况,可以引入 asyncScriptOnLoad以下HOC以确保在加载 JavaScript 资源后呈现包装的组件:

function withScript(url, WrappedComponent) {

  const LoadingElement = props =>  {
      return <div>Loading...</div>;
  }

  class Wrapper extends React.PureComponent {
    constructor(props) {
      super(props);
      this.state = {
        scriptLoaded: false
      };
    }
    render() {
      const AsyncScriptLoader = makeAsyncScriptLoader(url)(LoadingElement);
      if(this.state.scriptLoaded){
         return <WrappedComponent/>
      } 
      return (
        <AsyncScriptLoader
          asyncScriptOnLoad={() => {
            this.setState({scriptLoaded: true});
          }}
        />
      );
    }
  }
  return Wrapper;
}

现在谷歌地图组件可以这样渲染:

const GoogleMapsUrl = `https://maps.googleapis.com/maps/api/js?libraries=places&key=AIzaSyDurZQBXjtSzKeieXwtFeGe-jhZu-HEGQU`;
const App = withScript(GoogleMapsUrl, Autocomplete);

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

演示


推荐阅读