我的index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="google-signin-client_id" content= "my_client_id.apps.googleusercontent.com">
<meta name="google-signin-scope" content="profile email">
<script src="https://apis.google.com/js/client:platform.js?onload=start" async defer></script>
<script>
function start() {
console.log('script running')
gapi.load('auth2', function() {
auth2 = gapi.auth2.init({
client_id: 'my_client_id.apps.googleusercontent.com',
scope: 'profile email'
});
});
}
</script>
<title>React App</title>
</head>
<body>
<div id="root"></div>
</body>
</html>
在start()
功能中,我打印到控制台以查看它何时运行。
当我加载页面时,每隔一段时间start()
将在反应组件之后加载。
Login.js
componentDidMount() {
console.log(gapi.auth2.getAuthInstance())
}
在调试器中,您可以看到脚本在组件之后加载:
如果我刷新页面几次,它可以正常工作。但有时候它会起作用,有时则不然。
为什么呢?
答案 0 :(得分:4)
我认为在反应中加载脚本的最佳方法是使用容器组件。它是一个非常简单的组件,它允许您编写用于在组件而不是index.html中导入脚本的逻辑。您还需要在checkDidMount中检查后调用loadScript,确保不要多次包含该脚本。
改编自:https://www.fullstackreact.com/articles/how-to-write-a-google-maps-react-component/
像这样的东西。 。
componentDidMount() {
if (!window.google) {
this.loadMapScript();
}
else if (!window.google.maps) {
this.loadMapScript();
}
else {
this.setState({ apiLoaded: true })
}
}
loadMapScript() {
// Load the google maps api script when the component is mounted.
loadScript('https://maps.googleapis.com/maps/api/js?key=YOUR_KEY')
.then((script) => {
// Grab the script object in case it is ever needed.
this.mapScript = script;
this.setState({ apiLoaded: true });
})
.catch((err: Error) => {
console.error(err.message);
});
}
render() {
return (
<div className={this.props.className}>
{this.state.apiLoaded ? (
<Map
zoom={10}
position={{ lat: 43.0795, lng: -75.7507 }}
/>
) : (
<LoadingCircle />
)}
</div>
);
}
然后在另一个文件中:
const loadScript = (url) => new Promise((resolve, reject) => {
let ready = false;
if (!document) {
reject(new Error('Document was not defined'));
}
const tag = document.getElementsByTagName('script')[0];
const script = document.createElement('script');
script.type = 'text/javascript';
script.src = url;
script.async = true;
script.onreadystatechange = () => {
if (!ready && (!this.readyState || this.readyState === 'complete')) {
ready = true;
resolve(script);
}
};
script.onload = script.onreadystatechange;
script.onerror = (msg) => {
console.log(msg);
reject(new Error('Error loading script.'));
};
script.onabort = (msg) => {
console.log(msg);
reject(new Error('Script loading aboirted.'));
};
if (tag.parentNode != null) {
tag.parentNode.insertBefore(script, tag);
}
});
export default loadScript;
我知道它很多,但是当我第一次这样做时,当我发现有一种(相当)简单的方法在任何反应组件中包含任何脚本时,它是如此松懈。
编辑:其中一些我只是复制粘贴,但如果你没有使用create-react-app,你可能不得不替换一些ES6语法。
答案 1 :(得分:1)
我的建议:
将您的Google API脚本标记更改为此内容,删除async
和defer
<script src="https://apis.google.com/js/client:platform.js"></script>
摆脱你的启动功能,它现在将运行console.log
罚款和花花公子,但第二位代码将导致相同的问题,因为它也将异步运行。
修改您的反应代码,以便componentWillMount
调用该函数的内容:
componentWillMount() {
gapi.load('auth2', () => {
auth2 = gapi.auth2.init({
client_id: 'urhaxorid.apps.googleusercontent.com',
scope: 'profile email',
onLoad: () => {
this.setState({ mapLoaded: true });
}
});
});
}
componentDidMount() {
if (this.state.mapLoaded) {
console.log(gapi.auth2.getAuthInstance());
}
}
请记住,我不知道onLoad
对于谷歌api是什么,我不是100%确定如何最好地做setState
的事情,但它可能是一个起点。