[英]Rerendering state in React after async call
我正在嘗試在調用 Geolocation API 后將用戶的當前城市加載到頁面上。 但是,調用 geolocation 函數的主要組件是在位置 Promise 返回之前將狀態設置為 undefined。
我的目標是設置用戶當前位置的狀態。 但是,當我在 React 組件中調用 geolocate() 時, state.city 被設置為 undefined 因為它不等待 geolocation 函數返回任何內容。
我的地理定位功能:
const geolocate = async () => {
if (!navigator.geolocation) {
alert('Geolocation is not supported by your browser. Please search for a location to look for weather');
} else {
getCoordinates().then((position) => {
getCityByCoords(position)
.then((response) => {
return response;
})
.catch(err => console.log(err));
})
.catch(err => console.log(err));
}
}
const getCoordinates = () => {
return new Promise((resolve, reject) => {
navigator.geolocation.getCurrentPosition(
position => {
return resolve(position);
},
error => reject(error)
)}
);
};
// a call to my own API to make a request to Google's geocoding API
// response from this is coming back successfully
const getCityByCoords = (position) => {
const { latitude, longitude } = position.coords;
return axios.get('/city', {
params: {
lat: latitude,
lng: longitude
}
})
}
我的組件中的函數調用:
componentDidMount() {
this.getLocation();
}
getLocation() {
geolocate()
.then(
(response) => {
this.setState({
city: response,
isLoaded: true
})
},
(error) => {
this.setState({
isLoaded: true,
error
});
})
.then(() => {
this.setState({ isLoaded: 'false' });
})
}
我認為所有這些異步調用都讓我失望。
首先,您的geolocate
函數缺少 return 語句,因此您可以在組件中的函數調用中獲取位置結果。
此外,不要嵌套 Promises,如果你可以返回它們。 在以下代碼段中,我重寫了您的geolocate
函數:
const geolocate = async () => {
if (!navigator.geolocation) {
// better would be to throw an error here, so you can handle them in your component (or wherever else)
alert(
"Geolocation is not supported by your browser. Please search for a location to look for weather"
);
} else {
// return was missing
return getCoordinates()
.then(position => getCityByCoords(position))
.catch(err => console.log(err));
}
};
之后,讓我們解決您的問題:您沒有在構造函數中初始化您的狀態,因此在第一次渲染時,它對city
或isLoaded
一無所知。
如果您將狀態的初始化放入構造函數中,它應該打印您想要的城市,或一個簡單的“等待”段落:
class Geo extends React.Component {
constructor(props) {
super(props);
this.state = {
city: "",
isLoaded: false
};
}
componentDidMount() {
this.getLocation();
}
getLocation() {
geolocate()
.then(
response => {
this.setState({
city: response,
isLoaded: true
});
},
error => {
this.setState({
isLoaded: true,
error
});
}
)
.then(() => {
this.setState({ isLoaded: "false" });
});
}
render() {
if (!this.state.isLoaded) {
return <div>Waiting for Geolocation...</div>;
}
return <div>Geolocation: {this.state.city}</div>;
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.