[RN 4-2 프로젝트 개발]

2020. 2. 24. 23:47React Native/React Native 날씨 앱

반응형

 

현재 위치 정보를 가져와 해당 위치의 날씨와 온도를 표시

 


1) Weather API : Fetch API 사용해서 앱 외부의 날씨 데이터 가지고 오는 API

   (*) 회원가입 필수 - 가입 후 발송된 이메일 확인 후 인증

 

https://openweathermap.org/api

 

Weather API - OpenWeatherMap

We have combined Weather services and Satellite imagery in a simple and fast Agro API. We have also launched a Dashboard for it - it is a visual service where you can easily work with satellite, weather and historical data, soil temperature and moisture, a

openweathermap.org


2) 위치 정보 : react-native-geolocation-service 라이브러리

npm install -save react-native-geolocation-service

 

https://github.com/Agontuk/react-native-geolocation-service

 

Agontuk/react-native-geolocation-service

React native geolocation service for iOS and android - Agontuk/react-native-geolocation-service

github.com


 

3) 사용자 권한 설정 (안드로이드)

./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" />

    <application
      android:name=".MainApplication"
      android:label="@string/app_name"
      android:icon="@mipmap/ic_launcher"
      android:roundIcon="@mipmap/ic_launcher_round"
      android:allowBackup="false"
      android:theme="@style/AppTheme">
      <activity
        android:name=".MainActivity"
        android:label="@string/app_name"
        android:configChanges="keyboard|keyboardHidden|orientation|screenSize"
        android:windowSoftInputMode="adjustResize">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
      </activity>
      <activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />
    </application>

</manifest>


4) WeatherView 컴포넌트

./src/Screens/WeatherView/

index.tsx

(*) API_KEY 는 메일로부터 받은 본인의 것을 입력

더보기
import React, {useEffect, useState} from 'react';
import {FlatList, Alert} from 'react-native';
import Geolocation from 'react-native-geolocation-service';

import Styled from 'styled-components/native';

const Container = Styled.SafeAreaView`
  flex: 1;
  background-color: #EEE;
`;

const WeatherContainer = Styled(FlatList)``;

const LoadingView = Styled.View`
    flex: 1;
    justify-content: center;
    align-items: center;
`;
const Loading = Styled.ActivityIndicator`
    margin-bottom: 16px;
`;
const LoadingLabel = Styled.Text`
  font-size: 16px;
`;

const WeatherItemContainer = Styled.View`
  height: 100%;
  justify-content: center;
  align-items: center;
`;
const Weather = Styled.Text`
  margin-bottom: 16px;
  font-size: 24px;
  font-weight: bold;
`;
const Temperature = Styled.Text`
  font-size: 16px;
`;

interface Props {}

const API_KEY = '73bd07d674cc4569f650bad6f22dc79d';

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,
    });
    Geolocation.getCurrentPosition(
      position => {
        const {latitude, longitude} = position.coords;
        fetch(
          `http://api.openweathermap.org/data/2.5/weather?lat=${latitude}&lon=${longitude}&APPID=${API_KEY}&units=metric`,
        )
          .then(response => response.json())
          .then(json => {
            setWeatherInfo({
              temperature: json.main.temp,
              weather: json.weather[0].main,
              isLoading: true,
            });
          })
          .catch(error => {
            setWeatherInfo({
              isLoading: true,
            });
            showError('날씨 정보를 가져오는데 실패하였습니다.');
          });
      },
      error => {
        setWeatherInfo({
          isLoading: true,
        });
        showError('위치 정보를 가져오는데 실패하였습니다.');
      },
    );
  };

  const showError = (message: string): void => {
    setTimeout(() => {
      Alert.alert(message);
    }, 500);
  };

  useEffect(() => {
    getCurrentWeather();
  }, []);

  let data = [];
  const {isLoading, weather, temperature} = weatherInfo;
  if (weather && temperature) {
    data.push(weatherInfo);
  }

  return (
    <Container>
      <WeatherContainer
        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;

5) App 컴포넌트

더보기
import React from 'react';
import Styled from 'styled-components/native';

import WeatherView from '~/Screens/WeatherView';

const Container = Styled.View`
  flex: 1;
  background-color: #EEE;
`;

interface Props {}

const App = ({  }: Props) => {
  return (
    <Container>
      <WeatherView />
    </Container>
  );
};

export default App;

안드로이드 에뮬레이터 위치 허용 : Settings - Location - Allow 

(*) 안드로이드 에뮬레이터에서 위치 허용 기능이 정상적으로 동작하지 않으면, 직접 안드로이드 단말로 테스트할 것

 

 

반응형

'React Native > React Native 날씨 앱' 카테고리의 다른 글

[RN 4-1 프로젝트 준비]  (0) 2020.02.24