2017-04-09 38 views
14

我正在嘗試對componentWillMount方法中的API執行異步調用。事實上,我希望render方法在componentWillMount方法後執行,因爲我需要將props傳遞給我的render方法中的組件。componentWillMount中的異步調用在渲染方法後完成

這裏是我的代碼:

class TennisSearchResultsContainer extends React.Component { 
    componentWillMount() { 
    // TODO: Build markers for the map 
    // TODO: Check courtsResults object and database for tennis court 
    this.courtsMarkers = this.props.courtsResults.map((court) => { 
     return new google.maps.Marker({ 
     position: new google.maps.LatLng(JSON.parse(court.LOC).coordinates[1], JSON.parse(court.LOC).coordinates[0]), 
     title: court.NAME, 
     animation: google.maps.Animation.DROP 
     }); 
    }); 
    } 
    render() { 
    return <TennisSearchResults criterias={this.props.criterias} courtsMarkers={this.courtsMarkers} />; 
    } 
} 

我不那麼明白,爲什麼我的渲染方法似乎不等待異步調用完成並通過不確定的道具,我的子組件...

我對不對?我應該怎麼做才能解決這個問題?處理這個的方法是什麼?

+2

您需要使用'componentDidMount'來代替'componentWillMount',只有在組件被安裝到DOM之前運行一次。所以,不保證在AJAX調用之後組件將被渲染。 – Rowland

+0

你的代碼的哪部分是異步的?有很多谷歌地圖調用,並不清楚它是否是其中之一,或其他。 –

回答

24

您可能需要更好地理解javascript異步行爲。異步意味着「不要等待」。該任務將在後臺執行,其他代碼將繼續執行。管理這個的好方法是在組件上設置狀態。例如,當您輸入componentWillMount時,將loading狀態設置爲true。然後,當你的異步功能完成時,將該狀態設置爲false。在您的render功能中,您可以顯示「加載...」消息或數據。

下面是一些代碼,顯示了獲取數據異步的簡化示例以及如何處理React中的數據。在瀏覽器中打開開發人員工具並查看控制檯輸出,以更好地理解React生命週期。

class MyComponent extends React.Component { 
    constructor(props) { 
    super(); 

    console.log('This happens 1st.'); 

    this.state = { 
     loading: false, 
     data: '' 
    }; 

    } 

    loadData() { 
    // In real life you might use something like 'fetch' inside this 
    // function to get data. 
    // Since 'fetch' returns a promise, we can easily simulate that 
    // to keep the example simple. 
    var promise = new Promise((resolve, reject) => { 
     setTimeout(() => { 
     console.log('This happens 5th (after 3 seconds).'); 
     resolve('This is my data.'); 
     }, 3000); 
    }); 

    console.log('This happens 3rd.'); 

    return promise; 
    } 

    componentWillMount() { 

    console.log('This happens 2nd.'); 

    this.setState({ loading: true }); 
    this.loadData() 
    .then((data) => { 
     console.log('This happens 6th.'); 
     this.setState({ 
     data: data, 
     loading: false 
     }); 
    }); 
    } 

    render() { 

    if (this.state.loading) { 
     console.log('This happens 4th - when waiting for data.'); 
     return <h2>Loading...</h2>; 
    } 

    console.log('This happens 7th - after I get data.'); 
    return (
     <div> 
     <p>Got some data!</p> 
     <p>{this.state.data}</p> 
     </div> 
    ); 
    } 
} 

ReactDOM.render(
    <MyComponent />, 
    document.getElementsByClassName('root')[0] 
); 

這裏是working example on CodePen