react-async-script实现:包装组件

时间:2018-11-04 19:27:38

标签: reactjs google-maps google-maps-api-3 react-async

我正在尝试使用makeAsyncScriptLoader中的react-async-script包装需要Google Maps api的react组件。

在同一文件中(如果有所不同):

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 />来从另一个文件中调用该组件。

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

1 个答案:

答案 0 :(得分:0)

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

  

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

  

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

对于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;
}

现在Google Maps组件可以这样呈现:

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);

Demo