前言
我知道現在在github上有現成的React Google Maps的套件,但是想透過這次的研究,了解google maps api是如何運作的,下次應該就直接用套件了吧XD
目標
在全屏的Google Maps地圖上,只要點擊地圖,取得地圖上的坐標,就能知道那個地點的天氣
熱身(Optional)
依照Google官網上的api文件[1],和Youtube上的教學影片[2],建立一個有基本版面的地圖
整合至React
依照這個網站[3]的文章,建立Component後,先在Render()建立一個想要放入地圖的Div,再來componentDidMount放入在上面寫的initMap function,並且在index.html加入Google Maps Api的Javascript,就能完成一個在React上的簡單地圖。
點擊增加Marker
目前的地圖是靜態提供Marker,根據Google Maps Api的文件[4],我改寫了當中的map.addListener,把上面提供new google.maps.Marker的方法加進去,這樣你的React地圖點擊就會有新的Marker了!
刪除舊有的Marker
根據文件[5],map.setMap(null)只能隱藏標記,也不能隱藏我點擊增加的Marker,參考了文件[6],在Component上面增加了兩個Global Variable:map和markers[],加上setMapOnAll、clearMarkers、deleteMarkers的function,就能完整的刪除標記了。
原理
利用增加Marker後,把Marker推到markers的陣列:markers.push(marker),再map.addListener中先刪除Marker,才再新增。
坐標與Open Weather Api整合
在原有的程式整合這個Component後,我在程式原有的State加上lat和lng來儲存從Google Maps Api從來的坐標,並且提供Component onClick={handleClick}的的Callback function,來接從Component收到map.addListener產生的坐標。這樣在收到坐標的改變後,顯示天氣的元件也會隨著改變。不過在串接天氣Api的過程中,有一個很奇怪的問題:
Axios api 無限loop
我一開始想說把抓到的坐標放到我的State,但卻一直無限loop,把this.setState的lat、lng拿掉之後,就沒事了,真的很怪異,不知道誰能幫我解答XD
getLocationWeather(lat, lng, unit){
this.setState = ({
lat: lat,
lng: lng
}, () => {
//結論:糾結了一整個下午,為什麼加了上面的setState會導致Infinity Loop呢?
getLocationWeather(lat, lng, unit).then(weather => {
this.setState ({
...weather,
masking: true
}); alert(JSON.stringify(this.state.city));
});
});
if (this.props.units !== unit) {
this.props.onUnitChange(unit);
}
setTimeout(() => {
this.setState({
masking: false
});
}, 600)
}
發現原因
原來我在setState後面多打一個等於
this.setState = ({
lat: lat,
lng: lng
}, () => { ...
this.setState變成一個新的function,執行後面getLocationWeather的程式後,呼叫this.setState,結果就變成死循環了
這個發生的原因!
結語
在和Huli大大聊過後,發現自己的作品還不完整,還能添加更多的功能,也看到其他人的天氣作品,覺得自己還有一段很長的路要走。歡迎各位一起討論!
DEMO
參考連接
- https://developers.google.com/maps/documentation/javascript/tutorial?hl=zh-tw
- https://www.youtube.com/watch?v=Zxf1mnP5zcw
- https://code.tutsplus.com/tutorials/getting-started-with-react-and-jsx--cms-27352
- https://developers.google.com/maps/documentation/javascript/events?hl=zh-tw
- https://developers.google.com/maps/documentation/javascript/markers?hl=zh-tw
- https://developers.google.com/maps/documentation/javascript/examples/marker-remove?hl=zh-tw