我基本上是尝试在React组件类的componentWillMount()
函数内执行此操作。
const script = document.createElement("script");
script.src = "https://apis.google.com/js/client.js";
script.async = true;
script.onload = function() {
gapi.client.setApiKey(API_KEY);
gapi.client.load('youtube', 'v3');
this.setState({ gapiReady: true });
// ^ Doesn't work because `this` refers to the script rather than the component itself.
};
document.body.appendChild(script);
此处粘贴整个组件以确保完整性:
import React, { Component } from 'react';
import VideoPlayer from '../../components/VideoPlayer/VideoPlayer';
import VideoInfo from '../../components/VideoInfo/VideoInfo';
import SearchBox from '../../components/SearchBox/SearchBox';
import './App.css';
class App extends Component {
constructor(props, context) {
super(props, context);
this.state = {};
};
componentWillMount() {
const script = document.createElement("script");
script.src = "https://apis.google.com/js/client.js";
script.async = true;
script.onload = function() {
gapi.client.setApiKey(API_KEY);
gapi.client.load('youtube', 'v3');
this.setState({ gapiReady: true }); // Doesn't work because `this` refers to the script rather than the component
};
document.body.appendChild(script);
};
render() {
if (this.state.gapiReady) {
return (
<div className="wrap">
<div className="sidebar">
<SearchBox />
<VideoInfo videoId="vkRDOcma9Qk" />
</div>
<div className="content">
<VideoPlayer />
</div>
</div>
);
} else {
return (
<div>Loading...</div>
)
}
};
}
export default App;
我的目标是仅在脚本完全加载时在render()函数中呈现VideoInfo和VideoPlayer组件,否则这些组件上的代码将失败,因为它们依赖于已加载的脚本。
我是以错误的方式解决这个问题吗?
答案 0 :(得分:3)
首先,你应该做这样的事情是componentDidMount
,这样即使代码无法访问document
对象,代码仍然可以运行。如果您不进行服务器端渲染,这并不重要,但它是React中的常见模式。
要解决this
的问题,您可以使用箭头功能定义script.onload
。使用箭头函数定义的函数不会创建新的上下文,因此this
保持与定义函数的作用域相同。
TLDR将此componentWillMount
方法替换为:
componentDidMount () {
const script = document.createElement("script")
script.src = "https://apis.google.com/js/client.js"
script.async = true
script.onload = () => {
gapi.client.setApiKey(API_KEY)
gapi.client.load('youtube', 'v3')
this.setState({ gapiReady: true })
}
document.body.appendChild(script)
}