2020/03/07
현재 위치의 정보를 받아와서 날씨를 간단하게 표시하는 앱을 만들어 보려고한다.
날씨 데이터를 가져오기 위해서 OpenWeather에서 제공하는 날씨 API를 사용. OpenWeather
위치정보는 react-native-geolocation-service 라이브러리를 사용.
npm install --save react-native-geolocation-service
./android/app/src/main/AndroidManifest.xml
파일을 수정한다.<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="com.weatherapp"
>
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
... ...
</manifest>
import Geolocation from 'react-native-geolocation-service`;
...
Geolocation.getCurrentPosition(
position => {
...
},
error => {
...
}
);
import React, {useState, useEffect} from 'react';
import styled from 'styled-components/native';
import {FlatList, Alert} from 'react-native';
import Geolocation from 'react-native-geolocation-service';
interface Props {}
const API_KEY = '비밀쓰비밀쓰비밀쓰비밀쓰';
interface IWeather {
temperature?: number;
weather?: string;
isLoading: boolean;
}
const WeatherView = ({}: Props) => {
const [weatherInfo, setWeatherInfo] = useState<IWeather>({
temperature: undefined,
weather: undefined,
isLoading: false,
});
// 해당 위치의 날씨 정보를 가져오기 위한 함수
// 두 곳에서 호출하도록 설정하여, 당겨서 갱신하기 기능을 사용.
const getCurrentWeather = () => {
setWeatherInfo({
isLoading: false,
});
// 현재 위치의 위도(latitude)와 경도(longitude)를 가져옴
Geolocation.getCurrentPosition(
position => {
const {latitude, longitude} = position.coords;
// 가져온 위치 정보를 사용하여 Fecth API 사용
fetch(
`http://api.openweathermap.org/data/2.5/weather?lat=${latitude}&lon=${longitude}&APPID=${API_KEY}&units=metric`,
)
.then(res => res.json())
.then(json => {
setWeatherInfo({
temperature: json.main.temp,
weather: json.weather[0].main,
isLoading: true,
});
})
.catch(error => {
setWeatherInfo({
isLoading: true,
});
showError('날씨 정보를 가져오는데 실패하였다.');
});
},
// 위치 정보를 가져오지 못하면 error
error => {
setWeatherInfo({
isLoading: true,
});
showError('위치 정보를 가져오는데 실패했다.');
},
);
};
const showError = (message: string): void => {
setTimeout(() => {
Alert.alert(message);
}, 500);
};
// 화면 렌더링 이후 날씨 데이터를 가져옴. componentDidMount와 같음
useEffect(() => {
getCurrentWeather();
}, []);
let data = [];
const {isLoading, weather, temperature} = weatherInfo;
if (weather && temperature) {
data.push(weatherInfo);
}
return (
<Container>
<FlatList
onRefresh={() => getCurrentWeather()}
refreshing={!isLoading}
data={data}
keyExtractor={(item, index) => {
return `Weather-${index}`;
}}
ListEmptyComponent={
<LoadingView>
<Loading size="large" color="#1976d2" />
<LoadingLabel>Loading...</LoadingLabel>
</LoadingView>
}
renderItem={({item, index}) => (
<WeatherItemContainer>
<Weather>{(item as IWeather).weather}</Weather>
<Temperature>({(item as IWeather).temperature}'C)</Temperature>
</WeatherItemContainer>
)}
contentContainerStyle={{flex: 1}}
/>
</Container>
);
};
export default WeatherView;
// styled-components 부분은 생략
// error 메세지를 표시하는 함수
const showError = (message: string): void => {
setTimeout(() => {
Alert.alert(message);
}, 500);
};
onRefresh
에 당겨서 갱신할 때, 호출할 함수를 정의.
refreshing
에는 당겨서 갱신하기 기능을 사용하여 데이터를 갱신 중인지, 데이터 갱신이 끝났는지를 알려주기 위한 Boolean 값을 설정한다.