앱 개발/React-Native
[React-Native] 날씨 앱 만들기(5/6)_Weather
태기
2023. 1. 25. 13:34
Weather
날씨 api 받아오기
https://openweathermap.org/api/
Weather API - OpenWeatherMap
Please, sign up to use our fast and easy-to-work weather APIs. As a start to use OpenWeather products, we recommend our One Call API 3.0. For more functionality, please consider our products, which are included in professional collections.
openweathermap.org
1. 접속해서 회원가입, 로그인 하고 api-key를 받는다.
2. one-call-api 사용할거임
소스코드 수정
const [location, setLocation] = useState();
>>>>> 수정
const [days, setDays] = useState([]);
ask()
>>>>> 수정
getWeather()
- location 변수는 필요없어서 지우고 날씨들을 담을 days 배열 생성함
- 기존 ask function의 이름을 getWeather로 변경
날씨 불러오기
import {
View,
Text,
Dimensions,
ActivityIndicator, // [1]
StyleSheet,
ScrollView,
} from "react-native";
const API_KEY = "--------------------------------"; // [2]
...
setCity(location[0].city);
//// 추가 ///
const response = await fetch(
`https://api.openweathermap.org/data/2.5/onecall?lat=${latitude}&lon=${longitude}&exclude=alerts&appid=${API_KEY}&units=metric`
); // [3]
const json = await response.json();
setDays(json.daily);
...
/// 스크롤뷰 안에 View들 다 지우고 api에 받아온 거 사용하도록 수정
<ScrollView
pagingEnabled // 스크롤 화면 꽉 차게 함
horizontal // 가로로 스크롤
showsHorizontalScrollIndicator={false}
contentContainerStyle={styles.weather}
>
{days.length === 0 ? (
<View style={styles.day}>
<ActivityIndicator
color={white}
style={{ marginTop: 10 }}
size="large"
/>
</View>
) : (
days.map((day, index) => (
<View key={index} style={styles.day}>
<Text style={styles.temp}>
{parseFloat(day.temp.day).toFixed(1)} // [4]
</Text>
<Text style={styles.description}>{day.weather[0].main}</Text>
<Text style={styles.tinyText}>{day.weather[0].description}</Text>
</View>
))
)}
</ScrollView>
...
// 스타일 추가
tinyText: {
fontSize: 20,
},
[1] ActivityIndicator 추가하여 로딩 화면
[2] 날씨 api 사이트에서 발급받은 api-key 입력
[3] api call 링크 복붙하고 끝에 '&units=metric' 추가 >> 기존은 미국단위로 표시되어서 한국단위로 바꿔줌
[4] 소수점 1번째 자리까지만 표시
전체 소스코드
import * as Location from "expo-location";
import React, { useEffect, useState } from "react";
import {
View,
Text,
Dimensions,
ActivityIndicator,
StyleSheet,
ScrollView,
} from "react-native";
const { width: SCREEN_WIDTH } = Dimensions.get("window"); // 디바이스 화면 크기 불러옴
const API_KEY = "f1c0ecfa8da31108bbdea2ed6d47fe23";
export default function App() {
const [city, setCity] = useState("Loading...");
const [days, setDays] = useState([]);
const [ok, setOk] = useState(true);
const getWeather = async () => {
const { granted } = await Location.requestForegroundPermissionsAsync();
if (!granted) {
setOk(false);
}
const {
coords: { latitude, longitude },
} = await Location.getCurrentPositionAsync({ accuracy: 5 });
const location = await Location.reverseGeocodeAsync(
{ latitude, longitude },
{ useGoogleMaps: false }
);
setCity(location[0].city);
const response = await fetch(
`https://api.openweathermap.org/data/2.5/onecall?lat=${latitude}&lon=${longitude}&exclude=alerts&appid=${API_KEY}&units=metric`
);
const json = await response.json();
setDays(json.daily);
};
useEffect(() => {
getWeather();
}, []);
return (
<View style={styles.container}>
<View style={styles.city}>
<Text style={styles.cityName}>{city}</Text>
</View>
<ScrollView
pagingEnabled // 스크롤 화면 꽉 차게 함
horizontal // 가로로 스크롤
showsHorizontalScrollIndicator={false}
contentContainerStyle={styles.weather}
>
{days.length === 0 ? (
<View style={styles.day}>
<ActivityIndicator
color="white"
style={{ marginTop: 10 }}
size="large"
/>
</View>
) : (
days.map((day, index) => (
<View key={index} style={styles.day}>
<Text style={styles.temp}>
{parseFloat(day.temp.day).toFixed(1)}
</Text>
<Text style={styles.description}>{day.weather[0].main}</Text>
<Text style={styles.tinyText}>{day.weather[0].description}</Text>
</View>
))
)}
</ScrollView>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: "orange",
},
city: {
flex: 1.2,
justifyContent: "center",
alignItems: "center",
},
cityName: {
fontSize: 68,
fontWeight: "500",
},
weather: {},
day: {
width: SCREEN_WIDTH,
alignItems: "center",
},
temp: {
marginTop: 50,
fontSize: 178,
},
description: {
marginTop: -30,
fontSize: 60,
},
tinyText: {
fontSize: 20,
},
});