24/4/20 react-native 날씨 어플 만들어보기
2024. 4. 20. 23:19ㆍ카테고리 없음
흐음... 앱만들기를 한번 바워보자구요 하하하하하
일단 react-native는 expo라는 라이브러리가 쉽게 부가적인것을 제공해서 최적화 해준다는구먼요
노마드코더 클론코딩 오늘 해본것들을 복습해보자구~
expo 를 인스톨 하고 expo init 명령어를 통해 react-native 프레임을 만듭니다.
근데 이게 depricated라고 뜨는것을 보니 업데이트 안하나봄 앞으로는 뭘로해야하는 거징??
<App.js>
import { StatusBar } from "expo-status-bar"; // 스마트폰 상단에 알림등을 보여주는 바를 나타냄
import { useEffect, useState } from "react"; //react의 훅들을 차용하나봄
import {
ScrollView, //react-native는 모든 컴포넌트들을 import해서 쓰나 봄
Dimensions, //react랑은 다르군요 호호
StyleSheet,
ActivityIndicator,
Text,
View,
} from "react-native";
import * as Location from "expo-location"; //expo 로케이션이라는 라이브러리 인스톨받아야함
import { Fontisto } from "@expo/vector-icons"; //구름사진과 같은 아이콘을 받아올수 있음
const { width: screenWidth } = Dimensions.get("window"); //Dimensions를 통해 현재 화면의 크기정보를 가져옴
const API_KEY = "a5665c117c73b1089bdaec9b1f9"; //날씨 데이터를 받아오기위한 APIKEy
const icons = { //키값에 따른 value의 아이콘을 가져오기위한 오브젝트화
Clouds: "cloudy",
Rain: "rains",
Clear: "day-sunny",
Snow: "snow",
Drizzle: "rain",
Thunderstorm: "lightning",
Atmosphere: "cloudy-gusts",
};
export default function App() { //기본 구조는 react와 컴포넌트형식이 같다.
const [city, setCity] = useState("...loading"); //useState 오랜만에 보는 기분이넹 ㅎㅎ
const [days, setDays] = useState([]); //도시이름을 담을 city 비동기 통신 data를 담을 days
const [ok, setOk] = useState(true); //상태정보를 담을 ok로 나눈다.
const ask = async () => { //비동기 통신의 시작함수
const { granted } = await Location.requestForegroundPermissionsAsync(); //Location이라고 명명한
if (!granted) { //것에서 요 매서드를 호출한다.
setOk(false); //해당 오브젝트에는 승인되었는지 여부가 들었는데
} //승인 안됬으면 안됐다고 스테이트 변경해준다.
const {
coords: { latitude, longitude }, //승인 되었으면 일단 오브젝트 형식으로 위치정보를
} = await Location.getCurrentPositionAsync({ accuracy: 5 }); //요 매서드로 받아올수 있다.
const location = await Location.reverseGeocodeAsync( //awate로 다 되길 기다렸다가
{ //위도 경도 받은게 첫번째 인자로 들가고
latitude,
longitude,
},
{ useGoogleMaps: false } //구글맵을 안쓴다는 상태를 알리는 인자? ㅋㅋ
);
setCity(location[0].city); //await 달려있응께 다 끝나면 setCity가 이루어 지고
const URL = `https://api.openweathermap.org/data/2.5/forecast?lat=${latitude}&lon=${longitude}&appid=${API_KEY}&units=metric`; // 비동기 통신을 할 url정보
const res = await fetch(URL); //위도경도 apikey가 필요했다.
const json = await res.json(); //fetch로 data가져오고 json형식에서 파싱해주고
setDays(json.list); //해당 data중에서 list를 days라는 스테이트에 보관한다.
// const resres = json.list.map((i) => {
// return i.weather;
// });
// console.log(resres);
};
useEffect(() => { //useEffect 훅으로 첫 마운트시에 비동기 호출 수행하도록 조치
ask();
}, []);
return ( //return 안에 jsx형식으로 쓰는 것도 react랑 똑같다.
<View style={styles.container}> //태그가 다양하지는 않는데 전부 view로 하고
<View style={styles.city}>
<Text style={styles.cityName}>{city}</Text> //글자만 text라고 한다. 호호 그렇구먼
</View> //styles 어쩌고 하면서 밑에서 설정한 css를 가져온다.
<ScrollView //react와 달리 react-native는 자동적으로 스크롤이 생기지 않는다.
horizontal //요 스크롤 뷰라는 태그를 사용해야함
pagingEnabled //호리즌털을 가로스크롤링
showsHorizontalScrollIndicator={false} //페이징이네블드는 페이지별로 넘어가게함
contentContainerStyle={styles.weather} //요 태그에 style변화주려면 요 속성을 써야한다고함
>
{days.length === 0 ? ( //삼항연산자로 깔쌈하게 비동기 통신결과값이 없다면
<View style={{ ...styles.day, alignItems: "center" }}>
<ActivityIndicator></ActivityIndicator> //요 로딩창 보여주는 태그가 보여지게 조치
</View>
) : (
days.map((item, idx) => { //days라는 스테이트에 배열형식이 담겼으므로 익숙한
return ( //map 매서드로 태그를 뿌려주자
<View key={idx} style={styles.day}> //귀찮응께 일단 키는 idx로 해두고
<View //근데 얘네는 부모태그의 css를 자동으로 물려받지는 않나봄?
style={{ flexDirection: "row", justifyContent: "center" }} //신기한게 기본적으로 flex-col이라서
> //방향 바꾸고 싶으면 row로 바꿔야됨
<Text style={styles.temp}>{item.main.temp}</Text>
<Fontisto //아이콘 쓰려고 임포트 해온 태그에서
name={icons[item.weather[0].main]} //name을 일치시키면 해당 아이콘을 가져올수 있는데
size={60} //아이콘 사이트가 머라머라 헀는데 흐음... 아몰랑
color="white"
></Fontisto>
</View>
<Text style={styles.description}>{item.weather[0].main}</Text>
</View>
);
})
)}
</ScrollView>
</View>
);
}
const styles = StyleSheet.create({ //css 정의는 이런식으로 함 인라인으로 할수도 있는데
container: { //styleSheet으로 해야 자동완성도 되고 정리도 되고 좋음
flex: 1, //flex는 화면 내에서 비율로써 작동함
backgroundColor: "tomato",
},
city: {
flex: 1,
justifyContent: "center",
alignItems: "center",
},
cityName: {
color: "black",
fontSize: 68,
fontWeight: "500",
},
weather: {
backgroundColor: "teal",
},
day: {
fontSize: 50,
width: screenWidth, //요건 위에서 dimention으로 가져온 화면크기를 적용
alignItems: "center", //스마트폰 종류에 따라 가로세로 크기가 다르니 자주 쓸듯?
},
temp: {
marginTop: -30,
fontSize: 100,
},
description: {
fontSize: 60,
},
});
//복습 소감....
//react 와 비슷해서 익히는데 어려움은 없을것 같고
//다 숙달하면 재밌는 앱 하나 만들어 봐야겠다. 호호