[React] API

XIXIยท2022๋…„ 6์›” 30์ผ
0

๋Œ€๊ตฌAI์Šค์ฟจ

๋ชฉ๋ก ๋ณด๊ธฐ
46/57
post-thumbnail

๐ŸŒฑ ๋™๊ธฐ์™€ ๋น„๋™๊ธฐ

โœ๏ธ ๋™๊ธฐ

  • ์ž‘์—…(task)๋“ค์ด ์ˆœ์ฐจ์ ์œผ๋กœ ์ด๋ฃจ์–ด ์ง€๋Š” ๊ฒƒ
  • ๋‹ค๋ฅธ ์ž‘์—…๋“ค์„ blocking

โœ๏ธ ๋น„๋™๊ธฐ

  • ์žก์—…(task)๋“ค์ด ์ˆœ์ฐจ์ ์œผ๋กœ ์ด๋ฃจ์–ด์ง€์ง€ ์•Š์Œ
  • ๋‹ค๋ฅธ ์ž‘์—…๋“ค์€ non-blocking
  • Javascript๋ฅผ ์‚ฌ์šฉํ•œ ๋น„๋™๊ธฐ ํ†ต์‹  ๋ฐฉ์‹์„ Ajax(Asynchronous Javascript and XML)
  • Http์š”์ฒญ(GET, POST), ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ(click, over โ€ฆ), setTimeout, setInterval

โœ๏ธ ๋น„๋™๊ธฐ ์š”์†Œ

Callback

  • ์ฝœ๋ฐฑ ํ•จ์ˆ˜๋ž€ ์ธ์ž๋กœ ๋“ค์–ด์˜ค๋Š” ํ•จ์ˆ˜๋ฅผ ๋งํ•จ
  • ์ฝœ๋ฐฑ์€ ๋น„๋™๊ธฐ ํ†ต์‹ ์„ ํ•  ์ˆ˜ ์žˆ๋Š” ํŒจํ„ด
  • ๋ฌธ์ œ์ : ์ฝœ๋ฐฑ ํ—ฌ๋กœ ์ธํ•œ ์—๋Ÿฌ์ฒ˜๋ฆฌ ๋ถˆ๊ฐ€, ๊ฐ€๋…์„ฑ ์ €ํ•˜

๐ŸŒฑ ๋‚ ์”จ API ์‹ค์Šต

App.js

import logo from './logo.svg';
import './App.css';
import WeatherBox from './components/WeatherBox';
import WeatherButton from './components/WeatherButton';
import {Container} from 'react-bootstrap';
import 'bootstrap/dist/css/bootstrap.min.css'

function App() {
  return (
    <Container className = "vh-100">
      <div></div>
      <div className = "main-container">
        <WeatherBox />
        <WeatherButton />
      </div>
    </Container>
  );
}

export default App;

WeatherBox.js

import React from 'react'

const WeatherBox = () => {
  return (
    <div>
      <h3>๋Œ€๊ตฌ</h3>
      <h3>33๋„/ํ™”์”จ 230๋„</h3>
      <h3>๋”์›€</h3>
    </div>
  );
}

export default WeatherBox;

WeatherButton.js

import React from 'react'

const WeatherButton = () => {
  return (
    <div>WeatherButton</div>
  );
}

export default WeatherButton;

App.css

body {
  background: url("https://images.unsplash.com/photo-1514454529242-9e4677563e7b?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=870&q=80");
  height: 100vh;
  background-repeat: no-repeat;
  background-size: cover;
}

.main-container {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  height: 300px;
  text-align: center;
}

App.js API ๋ถˆ๋Ÿฌ์˜ค๊ธฐ

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

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

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 = //units=metric ์บ˜๋นˆ์„ ์„ญ์”จ๋กœ
        // let url = `https://api.openweathermap.org/data/2.5/weather?lat=${lat}&lon=${lon}&appid=${API_KEY}`;
        // `https://api.openweathermap.org/data/2.5/weather?q=${city}&appid=${API_KEY}`;
        'http://api.openweathermap.org/data/2.5/weather?lat=35.87222&lon=128.60250&appid=b4a0b63fb0a27cc709f6ea5ecd5f5d7d';
      //&units=metric
      const res = await fetch(url);
      const data = await res.json();
      setWeather(data);
      setLoading(false);
    } catch (err) {
      setAPIError(err.message);
      setLoading(false);
    }
  };

  const getCurrentLocation = () => {
    navigator.geolocation.getCurrentPosition((position) => {
      const { latitude, longitude } = position.coords;
      getWeatherByCurrentLocation(latitude, longitude);
      // console.log('ํ˜„์žฌ ์œ„์น˜', lat, lon);
    });
  };

  const getWeatherByCity = async () => {
    try {
      let url = `https://api.openweathermap.org/data/2.5/weather?q=${city}&appid=${API_KEY}`;
      //&units=metric
      const res = await fetch(url);
      const data = await res.json();

      setWeather(data);
      setLoading(false);
    } catch (err) {
      console.log(err);
      setAPIError(err.message);
      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://t4.ftcdn.net/jpg/04/97/80/99/360_F_497809944_FMo3DO6j7XSlb9rZKOlnqaaWoJhuZXBm.jpg');
    height : 100vh;
    background-repeat: no-repeat;  
    background-size: cover;
}

.weather-card{
    background-color: rgba(52,52,52,.7);
    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: #000;
    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: #ffc107;
  }

PublicNavbar.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;

Weather.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;

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-warning' : 'warning'}`}
        onClick={() => handleCityChange('current')}
      >
        Current Location
      </Button>

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

export default WeatherButton;

๐Ÿƒ ์–ด๋ ค์› ๋˜ ์  or ํ•ด๊ฒฐ๋ชปํ•œ ๊ฒƒ

css ํŒŒ์ผ ์ ์šฉ ์•ˆ๋ผ์„œ ์–ด๋ ค์› ๋‹ค.

๐Ÿ€ ํ•ด๊ฒฐ๋ฐฉ๋ฒ• ์ž‘์„ฑ

โœ๏ธ ์–ด๋–ป๊ฒŒ ํ•ด๊ฒฐ์„ ํ–ˆ๋Š”๊ฐ€?
โœ๏ธ ์ด๋ ‡๊ฒŒ ์ดํ•ด๋ฅผ ํ–ˆ๋‹ค
โœ๏ธ ์–ด๋””๊นŒ์ง€ ์ดํ•ดํ–ˆ์ง€?
โœ๏ธ ๋‹ค์Œ์— ์‹œ๋„ํ•ด๋ณผ ๋ฐฉ๋ฒ•
๊ธฐ์กด ์ฝ”๋“œ๋ž‘ ์ž‘์„ฑํ•œ ์ฝ”๋“œ ์ฐจ์ด๋ฅผ ์•Œ์•„๋ด์•ผ๊ฒ ๋‹ค.
App.css weather-card ํด๋ž˜์Šค์— background-color์— !important๋ฅผ ์ ์œผ๋‹ˆ ์ ์šฉ์ด ๋˜์—ˆ๋‹ค.

๐ŸŒท ํ•™์Šต ์†Œ๊ฐ

๋งŽ์€ ๊ฐœ๋…์„ ํ•œ๊บผ๋ฒˆ์— ๋ฐฐ์›Œ์„œ ์ •๋ฆฌํ•˜๋Š” ์‹œ๊ฐ„์ด ํ•„์š”ํ•œ ๊ฒƒ ๊ฐ™๋‹ค.

profile
Life is experience:)

0๊ฐœ์˜ ๋Œ“๊ธ€