2017-04-25 53 views
0

我基本上是試圖從React組件類的componentWillMount()函數中執行此操作。從第三方JS文件載入中設置ReactJS狀態

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; 

我的目標是隻渲染渲染()函數VideoInfo和VideoPlayer組件時,腳本完全加載,因爲此否則代碼組件將失敗,因爲它們依賴於已加載的腳本。

我該怎麼做呢?

回答

1

首先,你應該做這樣的東西是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) 
}