앱 개발/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,
  },
});