如何在ReactJS中使用窗口对象?

时间:2016-05-06 21:39:11

标签: javascript reactjs ecmascript-6

我想在index.html内加载Google APIs client library,而onLoad='someMethod'会在单独的javascript文件中调用方法。然后该方法将打印到控制台。

客户端库加载时没有任何问题,但是消息没有从控制台打印出来,我认为这是因为根本没有调用该方法。

这是我的index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Welcome</title>

    <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-1q8mTJOASx8j1Au+a5WDVnPi2lkFfwwEAa8hDDdjZlpLegxhjVME1fgjWPGmkzs7" crossorigin="anonymous">
</head>

<body>
    <div id="app"></div>
    <script src="lib/vendors.js"></script>
    <script src="build/bundle.js"></script>
    <script src="https://apis.google.com/js/client.js?onload=handleGoogleClientLoad"></script>
</body>

以下是包含handleGoogleClientLoad方法的javascript文件:

import React from 'react';
import ReactDOM from 'react-dom';

import {Button} from 'react-bootstrap';

class MyApp extends React.Component {

handleGoogleClientLoad() {
    console.log('Success on load');
}

render() {
    return (
        <div>
            <Button>Click Me</Button>
        </div>
    );
  }
}


const app = document.getElementById('app');

ReactDOM.render(<MyApp />, app);

如果这是普通的javascript,方法将如下所示:

window.handleGoogleClientLoad = function() {
  // Log to the console
};

es6中是否有与window对象类似的内容。

3 个答案:

答案 0 :(得分:10)

组件方法未附加到window对象。 MyApp.handleGoogleClientLoad不会与window.handleGoogleClientLoad混淆,这是Google API脚本可能尝试调用的内容。

如果您希望Google API在您的组件上调用方法,那么您将遇到一些麻烦,因为无法保证在加载Google API脚本之前或之后安装您的组件。如果要保证在安装组件后必须注入脚本,并在componentDidMount方法中注册该函数。您可以使用loadjs

之类的内容
componentDidMount() {
 window.handleGoogleClientLoad = function() {
  // log to console
 }
 loadjs('https://apis.google.com/js/client.js?onload=handleGoogleClientLoad')
}

答案 1 :(得分:0)

你的反应组件仍然可以使用window对象..但问题是你定义你的函数很好,但你不是在任何地方调用它(是url中的jsonp语法)那个剧本?)。如果您希望在安装组件时执行该功能,则可以使用component lifecycle hooks,特别是componentDidMount

class MyApp extends React.Component {

handleGoogleClientLoad() {
    console.log('Success on load');
}

componentDidMount(){
  this.handleGoogleClientLoad();
}

render() {
    return (
        <div>
            <Button>Click Me</Button>
        </div>
    );
  }
}

如果您想保留已有的语法,那么您可以继续按照您的建议访问window,但这绝对不是一种非常反应的方式

答案 2 :(得分:0)

一个老问题,但我在自己解决问题时就发现了。我正在使用React Helmet将东西放到<head>中。我如何做到的如下。当使用defer来加载gapi时,此处的关键是使用<script>。这意味着它在文档被解析之前不会运行,这意味着我们的onload函数window.gapiInit现在存在。

来自https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script#attr-defer

此布尔属性设置为向浏览器指示脚本应在文档解析后但在触发DOMContentLoaded之前执行。

import React from "react"

import { Helmet } from "react-helmet"

const HeadHelmet: React.FC = () => {
  if (typeof window != "undefined") { // needed if SSR
    window.gapiInit = () => {
      console.log({ gapiInit: true })
      // set state, what ever you need
    }
  }

  return (
    <Helmet>
      <script
        src="https://apis.google.com/js/api.js?onload=gapiInit"
        defer={true}
      ></script>
    </Helmet>
  )
}

export default HeadHelmet