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
날씨 api 가져오기
회원 가입 후 사용한다
로직
//1. 앱이 실행 되자 마자 현재 위치 기반의 날씨가 보인다
//2. 지금 현재 도시와 온도 , 날씨 상태 정보가 나온다
//3. 하단에 도시 버튼 5개 (현재위치, 다른 도시 4개)
//4. 버튼을 누를 때 마다 해당 되는 도시별 날씨가 보여진다
//5. 현재위치 버튼을 누르면 다시 현재위치 기반의 날씨 정보를 보여준다
//6. 데이터를 들고오는 동안 로딩 스피너가 돌아간다
위치 정보 가져오기
https://www.w3schools.com/html/html5_geolocation.asp
HTML Geolocation API
W3Schools offers free online tutorials, references and exercises in all the major languages of the web. Covering popular subjects like HTML, CSS, JavaScript, Python, SQL, Java, and many, many more.
www.w3schools.com
import { useEffect, useState } from 'react';
import './App.css';
//1. 앱이 실행 되자 마자 현재 위치 기반의 날씨가 보인다
//2. 지금 현재 도시와 섭씨/화씨 , 날씨 상태 정보가 나온다
//3. 하단에 도시 버튼 5개 (현재위치, 다른 도시 4개)
//4. 버튼을 누를 때 마다 해당 되는 도시별 날씨가 보여진다
//5. 현재위치 버튼을 누르면 다시 현재위치 기반의 날씨 정보를 보여준다
//6. 데이터를 들고오는 동안 로딩 스피너가 돌아간다
function App() {
const getCurrentLocation = () => {
navigator.geolocation.getCurrentPosition((position) => {
let lat = position.coords.latitude;
let lon = position.coords.longitude;
console.log('현재 위도 경도는?', lat, lon);
});
};
useEffect(() => {
getCurrentLocation();
}, []);
return <div>안녕텍스트</div>;
}
export default App;
날씨 api 들고오기
api 호출 함수 만들기
const getWeatherByCurrentLocation = async (lat, lon) => {
let url = `https://api.openweathermap.org/data/2.5/weather?lat=${lat}&lon=${lon}&appid=81523c3aa0ea13bf7e0d71967cd5d5d4`;
let response = await fetch(url);
let data = await response.json();
console.log('데이터 확인!', data);
};
리액트 부트스트랩 사용하기 (버튼 만들어주기)
https://react-bootstrap.github.io/getting-started/introduction
React-Bootstrap
The most popular front-end framework, rebuilt for React.
react-bootstrap.github.io
터미널에서 설치하기
npm install react-bootstrap bootstrap
사용하고 싶은 컴포넌트 파일 상단에 import 걸어주기
import { Button } from 'react-bootstrap';
Weather.box.js
import React from 'react';
const WeatherBox = ({ weather }) => {
console.log('웨더 정보 확인', weather);
return (
<div className="weather-box">
<div>{weather.name}</div>
<h2>30도 / 130화씨</h2>
<h3>흐림</h3>
</div>
);
};
export default WeatherBox;
{다이나믹 값} 으로 웨더 데이터에서 정보를 가져 온다
섭씨온도로 확인하기 위해서 추가할 것들
let url = `https://api.openweathermap.org/data/2.5/weather?lat=${lat}&lon=${lon}&appid=81523c3aa0ea13bf7e0d71967cd5d5d4&units=metric`;
url 뒤에 &units=metric 을 추가해준다
혹은 이렇게 추가하지 않고 섭씨/화씨 온도를 각각 따로 처리 해도 된다
섭씨로 표기 된 데이터를 바탕으로 화씨 온도를 표시해 주는 방법
import React from 'react';
const WeatherBox = ({ weather }) => {
console.log('웨더 정보 확인', weather);
return (
<div className="weather-box">
<div>{weather?.name}</div> {/* weather가 참이면 실행 (삼항연산자의 또다른 표기법) */}
<h2>
{weather?.main.temp}℃ / {((weather?.main.temp * 9) / 5 + 32).toFixed(2)}℉
</h2>
<h3>흐림</h3>
</div>
);
};
/* 섭씨를 화씨로 변환하기 (0°C × 9/5) + 32 = 32°F */
export default WeatherBox;
도시 추가하기 array를 만들어 관리한다
const cities = ['paris', 'new york', 'tokyo', 'seoul'];
import React from 'react';
import { Button } from 'react-bootstrap';
const WeatherButton = ({ cities }) => {
console.log('도시정보 확인', cities);
return (
<div>
<Button variant="warning">Current Location</Button>
{cities.map((item) => (
<Button variant="warning">{item}</Button>
))}
</div>
);
};
export default WeatherButton;
배열에 있는 도시들이 버튼으로 생성 됐다
리액트는 one-way 구조이다
app(부모)에 모든 정보를 넣어 놓고 자식들에게 정보를 나눠주는 형식
WeatherButton.js 에서 버튼 클릭시 해당 국가의 데이터를 app.js 로 바로 넘겨줄 수 없다
WeatherButton.js
import React from 'react';
import { Button } from 'react-bootstrap';
const WeatherButton = ({ cities, setCity }) => {
console.log('도시정보 확인', cities);
return (
<div>
<Button variant="warning">Current Location</Button>
{cities.map((item) => (
<Button variant="warning" onClick={() => setCity(item)}>
{item}
</Button>
))}
</div>
);
};
export default WeatherButton;
로딩 스피너 만들기
https://www.npmjs.com/package/react-spinners
react-spinners
A collection of react loading spinners. Latest version: 0.13.4, last published: a month ago. Start using react-spinners in your project by running `npm i react-spinners`. There are 669 other projects in the npm registry using react-spinners.
www.npmjs.com
npm install --save react-spinners
설치 후
app.js 상단에 임포트 걸기
import ClipLoader from "react-spinners/ClipLoader";
오늘 날짜 추가
const todayData = () => {
const week = ['월','화','수','목','금','토','일'];
let now = new Date();
let todayMonth = (now.getMonth()+1) > 9 ? (now.getMonth()+1) : (now.getMonth()+1);
let todayDate = now.getDate() > 9 ? now.getDate() : '0' + now.getDate();
let dayOfWeek = week[now.getDay()];
return todayMonth + '월 ' + todayDate + '일 ' + dayOfWeek + '요일'
}
날씨 아이콘 추가하기
open API 에 있는 날씨 아이콘을 살펴본다
https://openweathermap.org/weather-conditions
Weather Conditions - OpenWeatherMap
Weather Conditions Home Weather Conditions
openweathermap.org
id 값에 따라 날씨가 다르게 표시 되어 있다
App.js
WeatherBox.js 에 와서 props 로 id를 던져준다
const WeatherBox = ({weather, id})
icon URL 주소를 가지고 온다
<img className="img-fluid" src = {'http://openweathermap.org/img/wn/{icon}@2x.png'} />
아직 엑박으로 나오고 있지만 콘솔창에 확인해보면 id 값이 맞게 출력 되고 있다
이제 엑박을 어떻게 이미지로 나올 수 있게 수정하는 일만 남았다!
에러 해결
icon URL 주소가 잘못 되어 있어서 엑박으로 뜨게 된 것이었다
수정 전
<img className="img-fluid" src = {'http://openweathermap.org/img/wn/{icon}@2x.png'} />
수정 후 동적 값으로 주기 위해 $를 붙여 줬다
<img className="img-fluid" src={`http://openweathermap.org/img/wn/${icon}@2x.png`} />
아이디와 아이콘 값이 잘 출력 되고 그에 맞게 아이콘도 그림으로 잘 나오게 됐다
근데 get 404 에러가 떠있어서 추후에 다시 수정해야겠다
수정하면서 추가 된 내용들
https://uigradients.com/#Horizon
uiGradients - Beautiful colored gradients
uiGradients is a handpicked collection of beautiful color gradients for designers and developers.
uigradients.com
배경색 그라데이션
{Math.round(weather?.main.temp)}º
Math.round 함수 사용하여 소수점 아래 다 버리기
검색 기능 추가하기
const [query, setQuery] = useState('');
App.js
/* 검색 기능 */
const search = async (e) => {
if(e.key === "Enter"){
fetch(`https://api.openweathermap.org/data/2.5/weather?q=${query}&appid=${API_KEY}&units=metric`)
.then(res => res.json())
.then(result => {
setWeather(result);
setQuery('');
//console.log("result 확인", result);
})
}
}
검색창에 도시를 입력하고 엔터를 누르면
url에 동적값으로 도시 이름이 들어가게 된다 ${query}
기온에 따라 배경 색상 바뀌게 하기
className={(typeof weather.main != "undefined")
? ((weather.main.temp > 26)
? 'container_warm' : 'container') : 'container'}
기온이 26도 이상일 때 container의 클래스네임을 다르게 부여하여 색상을 바꿔준다
하단의 버튼에 없는 도시들도 검색하면 바로 정보가 나오고 26도 이상일 때 배경색이 바뀐다
며칠 지나니까 에러 뜨고 데이터가 넘겨지는게 안되어서 코드 수정 했다
현재 위치 정보가 아예 뜨지 않는 상태였음
수정 전
/* 현재 위치의 위도 경도 가져오기 */
const getCurrentLocation = () => {
navigator.geolocation.getCurrentPosition((position) => {
let lat = position.coords.latitude;
let lon = position.coords.longitude;
//console.log('현재 위도 경도는?', lat, lon);
getWeatherByCurrentLocation(lat, lon);
});
};
수정 후
/* 현재 위치의 위도 경도 가져오기 */
const getCurrentLocation = () => {
navigator.geolocation.getCurrentPosition((position) => {
const { latitude, longitude } = position.coords;
getWeatherByCurrentLocation(latitude, longitude);
});
};
- 변수 수정
수정 전
/* 현재 위치의 날씨 정보 */
const getWeatherByCurrentLocation = async (lat, lon) => {
let url = `https://api.openweathermap.org/data/2.5/weather?q=lat=${lat}&lon=${lon}&appid=${API_KEY}&units=metric`;
let response = await fetch(url);
let data = await response.json();
//console.log('데이터 확인!', data);
setWeather(data);
setId(data.weather[0].id);
setIcon(data.weather[0].icon);
setLoading(false); //스피너 종료
};
수정 후
/* 현재 위치의 날씨 정보 */
const getWeatherByCurrentLocation = async (lat, lon) => {
try {
let url = `https://api.openweathermap.org/data/2.5/weather?lat=${lat}&lon=${lon}&appid=${API_KEY}`;
let response = await fetch(url);
let data = await response.json();
setWeather(data);
setIcon(data.weather[0].icon);
setLoading(false);
} catch (err) {
setError(err.message);
setLoading(false);
}
};
- try-catch 사용해서 에러처리
수정 전
useEffect((city) => {
/* useEffect는 componentDidUpdate 역할도 한다 */
/* useEffect 는 한 곳에서 정리한다 */
if (city === '') {
setLoading(true);
getCurrentLocation();
} else {
setLoading(true);
getWeatherByCity();
}
}, [city]);
수정 후
useEffect(() => {
if (city === '') {
setLoading(true);
getCurrentLocation();
} else {
setLoading(true);
getWeatherByCity();
}
}, [city]);
city 인자 넘겨받지 않고 뺌
수정 전
return (
/* UI를 보여주는 곳 */
<div>
{/* 스피너 true일 때의 조건 */}
{loading ? (
<div className="container">
<ClipLoader color="#ff0000" loading={loading} size={100} />
</div>
) : (
<div className={(typeof weather.main != "undefined")
? ((weather&&weather.main.temp > 26)
? 'container_warm' : 'container') : 'container'}>
<div className='search_box'>
<input
type="text"
placeholder='Search...'
onChange={e=>setQuery(e.target.value)}
value={query}
onKeyPress={search}
>
</input>
</div>
<WeatherBox weather={weather} id={id} icon={icon}/> {/* props로 넘기기 */}
<WeatherButton cities={cities} selectCity={city} handleCityChange={handleCityChange} /> {/* setCity라는 함수를 props로 넘겨준다 */}
</div>
)}
</div>
);
수정 후
return (
/* UI를 보여주는 곳 */
<div>
{/* 스피너 true일 때의 조건 */}
{loading ? (
<div className="container">
<ClipLoader color="#ff0000" loading={loading} size={100} />
</div>
) : !error ? (
<div className={typeof weather.main != 'undefined' ? (weather && weather.main.temp > 26 ? 'container_warm' : 'container') : 'container'}>
<div className="search_box">
<input type="text" placeholder="Search..." onChange={(e) => setQuery(e.target.value)} value={query} onKeyPress={search}></input>
</div>
<WeatherBox weather={weather} icon={icon} /> {/* props로 넘기기 */}
<WeatherButton cities={cities} selectCity={city} handleCityChange={handleCityChange} /> {/* setCity라는 함수를 props로 넘겨준다 */}
</div>
) : (
error
)}
</div>
);
error 에러처리
'Dev. > React' 카테고리의 다른 글
React :: shopping site 만들기 01 /폰트어썸 리액트 (0) | 2022.09.15 |
---|---|
React :: Router / Restful Route (0) | 2022.09.05 |
React :: 라이프 사이클 (0) | 2022.08.24 |
React :: 클래스 컴포넌트 (0) | 2022.08.22 |
React :: 가위바위보 게임 만들기 (0) | 2022.08.17 |
댓글