6/30 개발일지

정명환·2022년 6월 30일
0

대구 ai 스쿨

목록 보기
47/79

1)학습한 내용

날씨 앱 만들기

날씨 정보 api 가져오기
https://openweathermap.org/api

현재 위치 가져오기
https://www.w3schools.com/html/html5_geolocation.asp

비동기 방식
잡업(task)들이 순차적으로 이루어지지 않는다. 다른 작업들은 non-blocking.

callback
콜백 함수는 인자로 들어오는 함수를 칭한다.
문제점 : 콜백 헬로 인한 에러처리 불가와 가독성 X

promise
비동기 통신의 결과와 상태를 저장하는 객체이다.
후속처리 메서드로 then,catch,finally가 있다.

async/await
promise의 복잡성으로 인해 나온 비동기 패턴 더 사용하기 편하다.

App.js

import './App.css';
import WeatherBox from './components/WeatherBox';
import WeatherButton from './components/WeatherButton';
import {Container} from 'react-bootstrap';
import React, {useState, useEffect} from 'react';
import {ClipLoader} from 'react-spinners';
import 'bootstrap/dist/css/bootstrap.min.css';

const API_KEY = '5c0e4665db050c6343ab348328c9270c'
const cities = ['paris','new york', 'tokyo', 'seoul'];

const App = () => {
  const [loading, setLoading] = useState(false);
  const [city, setCity] = useState(null);
  const [weather, setWeather] = useState(null);
  const [apiError, setAPIError] = useState('');

  const getWeatherByCurrentLocation = async (lat, lon) => {
    console.log('현재 위치', lat, lon);
    //비동기 처리
    try {
      let url = `https://api.openweathermap.org/data/2.5/weather?lat=${lat}&lon=${lon}&appid=${API_KEY}`;
      //let url = 'https://api.openweathermap.org/data/2.5/weather?lat=35.8779863&lon=128.5795303&appid=5c0e4665db050c6343ab348328c9270c&units=metric';
      const res = await fetch(url);
      const data = await res.json();
      setWeather(data);
      setLoading(false);    
    }
    catch (err) {
      console.log(err.message);
      setLoading(false);   
    }
  };

  function getCurrentLocation() {
    navigator.geolocation.getCurrentPosition((position) => {
      const { latitude, longitude } = position.coords;
      getWeatherByCurrentLocation(latitude, longitude);
     // console.log('현재위치?', latitude, longitude);
    });
  };

  const getWeatherByCity = async () => {
    try {
      let url = `https://api.openweathermap.org/data/2.5/weather?q=${city}&appid=${API_KEY}`;
      const res = await fetch(url);
      const data = await res.json();
      setWeather(data);
      setLoading(false);   
    }catch(err){
      console.log(err);
      console.log(err);
      setLoading(false);   
    }
  };

  useEffect(()=>{
    if(city == null){
      setLoading(true);   
      getCurrentLocation();
    }else{
      setLoading(true); 
      getWeatherByCity();
    }
  },[city]);

  const handleCityChange = (city) => {
    if(city === 'current'){
      setCity(null);
    }else{
      setCity(city);
    }
  };

  return (
    <Container className="vh-100">
    {loading ? (
      <div className="w-100 vh-100 d-flex justify-content-center align-items-center">
        <ClipLoader color="#f86c6b" size={150} loading={loading} />
      </div>
    ) : !apiError ? (
      <div class="main-container">
        <WeatherBox weather={weather} />
        <WeatherButton
          cities={cities}
          handleCityChange={handleCityChange}
          selectedCity={city}
        />
      </div>
    ) : (
      apiError
    )}
  </Container>
  );
}

export default App;

App.css

body{
  background: url('https://images.pexels.com/photos/1631677/pexels-photo-1631677.jpeg?cs=srgb&dl=pexels-abdullah-ghatasheh-1631677.jpg&fm=jpg') no-repeat;
  height: 100vh;
  background-size: cover;
}

.weather-card{
  background-color: rgba(255,255,255,.9)!important;
  padding: 50px;
  border: 2px solid #fff;
  border-radius: 20px;
  max-width: 700px;
  width:100%;
  height: 300px;
}
.main-container{
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  height: 100%;
  
}
.menu-container{
  display: flex;
  justify-content: center;
  background-color: rgba(52,52,52,.6);
  border-radius: 60px;
  max-width: 700px;
  width:100%;
  padding: 30px;
  margin-top: 30px;
}
.menu-container Button{
  margin-right:30px;
}

.menu-container Button:hover{
  background-color: gray;
}

components/PublicNavar.js

import React from 'react';
import { Navbar, Nav } from 'react-bootstrap';

const PublicNavbar = () => {
  return (
    <Navbar bg="light" expand="lg" className="position-fixed navbar-fixed">
      <Navbar.Brand></Navbar.Brand>
      <Nav className="mr-auto"></Nav>
      <Nav>
        <a
          href="https://github.com/dhminh1024/cs_weather_app"
          target="_blank"
          rel="noreferrer"
        ></a>
      </Nav>
    </Navbar>
  );
};

export default PublicNavbar;

components/WeatherBox.js

import React from 'react';
import { Card } from 'react-bootstrap';

const WeatherBox = ({ weather }) => {
  const temperatureC =
    weather && weather.main ? (weather.main.temp - 273.15).toFixed(2) : '';
  const temperatureF =
    weather && weather.main
      ? (((weather.main.temp - 273.15) * 9) / 5 + 32).toFixed(2)
      : '';
  return (
    <Card className="weather-card">
      {/* <Card.Img src="holder.js/100px270" alt="Card image" /> */}
      <Card.ImgOverlay className="d-flex flex-column justify-content-center text-center">
        <Card.Title>{weather?.name}</Card.Title>
        <Card.Text className="text-success h1">
          {`${temperatureC} °C / ${temperatureF} °F`}
        </Card.Text>
        <Card.Text className="text-info text-uppercase h2">
          {weather && weather.weather[0]?.description}
        </Card.Text>
      </Card.ImgOverlay>
    </Card>
  );
};

export default WeatherBox;

components/WeatherButton.js

import React from 'react';
import { Button } from 'react-bootstrap';

const WeatherButton = ({ cities, selectedCity, handleCityChange }) => {
  return (
    <div class="menu-container">
      <Button
        variant={`${selectedCity === null ? 'outline-secondary' : 'secondary'}`}
        onClick={() => handleCityChange('current')}
      >
        Current Location
      </Button>

      {cities.map((city) => (
        <Button
          variant={`${selectedCity === city ? 'outline-secondary' : 'secondary'}`}
          onClick={() => handleCityChange(city)}
        >
          {city}
        </Button>
      ))}
    </div>
  );
};

export default WeatherButton;

실습 결과

2) 학습내용 중 어려웠던 점

X

3) 해결방법

X

4) 학습소감

api와 여러가지 기능들을 만드는 것이 아니라 받아와서 작성하는 것 만으로도 쉽게 작동되니 역시 검색하는 능력과 어떤 좋은 것이 있는 지 폭 넓은 지식이 필요하다는 것을 느꼈습니다.

profile
JAMIHs

0개의 댓글