230607 - React

๋ฐฑ์Šน์—ฐยท2023๋…„ 6์›” 7์ผ
1

๐Ÿšฉ React

๋‚ ์”จ API

๐Ÿ“ ์„ค๋ช…

  • ์™ธ๋ถ€ ๋‚ ์”จ API๋ฅผ ๊ฐ€์ ธ์™€์„œ ํ™”๋ฉด์— ์ถœ๋ ฅํ•˜๊ธฐ


โœ’๏ธ ์‚ฌ์šฉ๋ฒ•

์ž…๋ ฅ

App.js

import { useEffect, useState } from "react";
import WeatherBox from "./components/WeatherBox";
import WeatherButton from "./components/WeatherButton";
import PacmanLoader from "react-spinners/PacmanLoader";
import "bootstrap/dist/css/bootstrap.min.css"; // !๋ถ€ํŠธ์ŠคํŠธ๋žฉ css ์—ฐ๊ฒฐ
import "./App.css";

function App() {
  // * 4. ๋‚ ์”จ ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•  useState
  const [weather, setWeather] = useState(null); //๋‚ ์”จ๋ฐ์ดํ„ฐ
  // * 6. ํ˜„์žฌ ์„ ํƒํ•œ ๋„์‹œ๊ฐ€ ์–ด๋”˜์ง€ ์ €์žฅํ•˜๋Š” useState
  const [city, setCity] = useState("current");
  // * 8. loading ์„ค์ •์„ ์ €์žฅํ•˜๋Š” useState
  const [loading, setLoading] = useState(true);
  // * 5. ๋„์‹œ ์ด๋ฆ„์„ ๋ฐฐ์—ด๋กœ ์„ ์–ธ
  const cities = ["sydney", "oslo", "baghdad", "paris"];

  // * 1. ํ˜„์žฌ ์œ„์น˜ ๊ธฐ๋ฐ˜ ๋‚ ์”จ ์ถœ๋ ฅํ•˜๋Š” ํ•จ์ˆ˜ ์ •์˜
  const getCurrentLocation = () => {
    navigator.geolocation.getCurrentPosition((position) => {
      let lat = position.coords.latitude; // ์œ„๋„
      let lon = position.coords.longitude; // ๊ฒฝ๋„
      //console.log('ํ˜„์žฌ ๋‚ด ์œ„์น˜๋Š”?',lat,lon)

      // * 2-2. ํ•ด๋‹น ์œ„์น˜์˜ ๋‚ ์”จ๋ฅผ ๋ถˆ๋Ÿฌ์˜ด
      getWeatherByCurrentLocation(lat, lon);
    });
  };

  // * 2. ์ขŒํ‘œ๋ฅผ ์ด์šฉํ•˜์—ฌ ๋‚ ์”จ API๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” ํ•จ์ˆ˜
  const getWeatherByCurrentLocation = async (lat, lon) => {
    // * 8-2. setLoading ์‹คํ–‰
    setLoading(true);
    let url = `https://api.openweathermap.org/data/2.5/weather?lat=${lat}&lon=${lon}&appid=83aeb80a15d50ee7a248d29575f07e8d&units=metric`;
    let response = await fetch(url);
    let data = await response.json();
    setWeather(data);
    // * 8-3. setLoading ์ข…๋ฃŒ
    setLoading(false);
  };

  // * 7. ๋„์‹œ ์ด๋ฆ„์„ ์ด์šฉํ•˜์—ฌ ๋‚ ์”จ API๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” ํ•จ์ˆ˜
  const getWeatherByCity = async () => {
    // * 8-2. setLoading ์‹คํ–‰
    setLoading(true);
    let url = `https://api.openweathermap.org/data/2.5/weather?q=${city}&appid=83aeb80a15d50ee7a248d29575f07e8d&units=metric`;
    let response = await fetch(url);
    let data = await response.json();
    setWeather(data);
    // * 8-3. setLoading ์ข…๋ฃŒ
    setLoading(false);
  };

  // * 3. ์ฒ˜์Œ ํ™”๋ฉด ์ถœ๋ ฅ ์‹œ ๋”ฑ ํ•œ๋ฒˆ๋งŒ ๋ฐœ์ƒ๋˜๋„๋ก ํ•จ
  // * 6-2. city ๋ณ€์ˆ˜๊ฐ€ current์™€ ๊ฐ™์œผ๋ฉด getCurrentLocation() ์‹คํ–‰
  // * 7-2. city ๋ณ€์ˆ˜๊ฐ€ ๋ฐ”๋€Œ๋ฉด getWeatherByCity ์‹คํ–‰. useEffect()๋ฅผ ํ•˜๋‚˜๋กœ ํ•ฉ์นจ
  useEffect(() => {
    if (city === "current") {
      getCurrentLocation();
    } else {
      getWeatherByCity();
    }
  }, [city]);

  // // * 6-2. city ๋ณ€์ˆ˜๊ฐ€ ๋ฐ”๋€” ๋•Œ๋งˆ๋‹ค console์‹คํ–‰
  // useEffect(() => {
  //   getWeatherByCity();
  //   console.log("์„ ํƒํ•œ ๋„์‹œ๋Š” city??", city);
  // }, [city]);

  return (
    <>
      {loading ? (
        <div className='container'>
          <PacmanLoader color="#000" speedMultiplier={2} />
        </div>
        ) : (
        <div className='container'>
          <WeatherBox weather={weather} />
          <WeatherButton cities={cities} setCity={setCity} />
        </div>
      )}
    </>
    
    //   <div className="container">
    //   {/* // * 9. ๋กœ๋”ฉํ• ๋•Œ๋งŒ ๋กœ๋”๊ฐ€ ๋ณด์ด๋„๋ก ํ•จ */}
    //   {loading ? <PacmanLoader color="#fff" height={40} speedMultiplier={1} /> : null}
    //   {/*// * 4. ํ™”๋ฉด์— ๋‚ ์”จ ์ถœ๋ ฅ. props๋กœ WeatherBox๋กœ ๋‚ ์”จ ๋ฐ์ดํ„ฐ ๋ณด๋ƒ„ */}
    //   <WeatherBox weather={weather} />
    //   {/*// * 6-2. props๋กœ WeatherButton์œผ๋กœ ๋ฐ์ดํ„ฐ ๋ณด๋ƒ„ */}
    //   <WeatherButton cities={cities} setCity={setCity} />
    // </div>
  );
}

export default App;



App.css

body { background: url('./img/weather.jpg') no-repeat center center / cover; height: 100vh; }
.container { display: flex; flex-direction: column; justify-content: center; align-items: center; height: 100vh; }
.weather-box { width: 100%; max-width: 700px; background: rgba(184, 184, 184, 0.7); text-align: center; border-radius: 24px; padding: 50px 0 20px; margin-bottom: 20px; }
.weather-button { padding: 5px 30px; background: rgba(0, 0, 0, 0.4); border-radius: 60px; text-align: center; }
.weather-button button { margin: 5px; }



WeatherBox.jsx

import React from "react";

const WeatherBox = ({ weather }) => {
  console.log("WeatherBox์ปดํฌ๋„ŒํŠธ์˜ weather", weather);
  // * 1. ๋‚ ์”จ ์•„์ด์ฝ˜์„ ํ‘œ์‹œํ•˜๋Š” ๋ณ€์ˆ˜ ์ •์˜
  const iconNow = weather?.weather[0].icon;
  return (
    <div className="weather-box">
      {/* ๋ถ€ํŠธ์ŠคํŠธ๋žฉ */}
      <h3 className="h5 text-danger">{weather?.name}</h3>
      <h1 className="fw-semibold">
        {weather?.main.temp} โ„ƒ / {weather?.main.humidity}%
      </h1>
      <div className="text-primary h3 text-uppercase fw-semibold">
        {weather?.weather[0].description}
      </div>
      <div>
        {/* // * 1-2. ๋‚ ์”จ ์•„์ด์ฝ˜์„ ํ‘œ์‹œํ•˜๋Š” ๋ณ€์ˆ˜ ์‚ฌ์šฉ */}
        <img src={`https://openweathermap.org/img/wn/${iconNow}@2x.png`} />
      </div>
    </div>
  );
};

export default WeatherBox;
// {weather && weather.name}
// {weather?.name}



WeatherButton.jsx

import React from "react";
import Button from "react-bootstrap/Button"; // ๋ถ€ํŠธ์ŠคํŠธ๋žฉ(์ปดํฌ๋„ŒํŠธ๋กœ ์‚ฌ์šฉํ•  ๋•Œ๋Š” importํ•ด์•ผ ํ•จ)

const WeatherButton = ({ cities, setCity }) => {
  return (
    <div className="weather-button">
      {/* ๋ถ€ํŠธ์ŠคํŠธ๋žฉ */}
      <Button variant="warning" onClick={() => setCity("current")}>
        Current Location
      </Button>
      {cities.map((city, index) => ( // * 1. city ์•ˆ์˜ ๊ฐ๊ฐ์˜ array์˜ item(๋ฒ„ํŠผ)์„ ํ™”๋ฉด์— ์ถœ๋ ฅ
          <Button
            variant="outline-warning"
            key={index}
            onClick={() => setCity(city)}
          >
            {city}
            {/* ๋‚ด๊ฐ€ ๋ˆ„๋ฅธ ๋„์‹œ์˜ ์ด๋ฆ„์ด ๋“ค์–ด๊ฐ€๊ฒŒ */}
          </Button>
        )
      )}
    </div>
  );
};

export default WeatherButton;



์ถœ๋ ฅ

  • ์ด๋ฏธ์ง€๋กœ ๋Œ€์ฒด


๐Ÿ”— ์ฐธ๊ณ  ๋งํฌ & ๋„์›€์ด ๋˜๋Š” ๋งํฌ






๐Ÿšฉ React Bootstrap

Tailwind

๐Ÿ“ ์„ค๋ช…

  • ์™ธ๋ถ€ ๋‚ ์”จ API๋ฅผ ๊ฐ€์ ธ์™€์„œ ํ™”๋ฉด์— ์ถœ๋ ฅํ•˜๊ธฐ


โœ’๏ธ ์‚ฌ์šฉ๋ฒ•

์ž…๋ ฅ

App.js

import './App.css';
import Tailwind from './Tailwind';

function App() {
  return (
    <>
      <Tailwind />
    </>
  );
}

export default App;



App.css

@tailwind base;
@tailwind components;
@tailwind utilities;



Tailwind.jsx

import React from 'react'

export default function Tailwind() {
  return (
    <>
      <div className='border-4 border-lime-600 m-5 p-20'>
        <h1 className='text-sm text-end'>ํ…Œ์ผ์œˆ๋“œ ์‚ฌ์šฉ</h1>
        <h1 className='text-3xl text-blue-800'>ํ…Œ์ผ์œˆ๋“œ ์‚ฌ์šฉ</h1>
      </div>
      <button className=' bg-orange-400 py-3 px-10 rounded-full'>BUTTON</button>
    </>
  )
}



์ถœ๋ ฅ

  • ์ด๋ฏธ์ง€๋กœ ๋Œ€์ฒด

๐Ÿ”— ์ฐธ๊ณ  ๋งํฌ & ๋„์›€์ด ๋˜๋Š” ๋งํฌ






profile
๊ณต๋ถ€ํ•˜๋Š” ๋ฒจ๋กœ๊ทธ

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