페이지를 로드 하자마자 데이터를 보여줘야하는 상황이라면
useEffect()에서 호출하고 두 번째 인자로는 빈 배열을 전달한다.
그러면 최초 랜더링 시 데이터를 로드할 수 있다.
어떠한 동작에 의해서 데이터를 보여주고 싶다면 이벤트 핸들러에서 요청한다.
state를 어디에서 관리해야 하는지에 대해서 고려해서 선언한다.
App에서 관리하면 props로 전달할 수 있기는하지만 수정할 경우
App단위 전체로 리랜더링 되므로 비효율적이다.
function ItemList() {
const [users, setUsers] = useState();
useEffect(
() => {
fetch('https://jsonplaceholder.typicode.com/users')
.then(response => response.json())
.then(responseUser => setUsers(responseUser)) // 반환된 객체를 state쪽에 설정해준다.
//.then(response => console.log(response));
// response.json()에서 반환되는 값이 매개변수(responseUser)가 되는 것
}
);
return (
<div>
{ users && users.map(user => <Item user={ user } key={ user.id }/>) }
{/* 최초에 로드될 때 useEffect가 마운트 제일 마지막 시점에 user객체를 불러들인다.
그보다 먼저 마운트되는 return 구문은 usermap이 없는 상태이기 때문에 오류가 발생한다.
그래서 user&& users.map구문이 필요하다. */}
</div>
);
}
날씨 API 사용해서 오늘의 날씨 페이지 만들기 예제
const { useState, useEffect } = React;
const API_KEY = '94491d2466105d8873d696dd9429a1c1';
function Weather() {
const [position, setPosition] = useState({});
const [cityname, setCityname] = useState('');
const [weather, setWeather] = useState({});
const [wind, setWind] = useState({});
useEffect (
() => {
/* 위치 정보에 대한 조회가 완료된 이후 날씨 정보 api로 요청이 되어야하므로
두 가지 비동기 요청에 대한 순서를 반드시 정해서 수행해야만 한다. */
new Promise((resolve, reject) => {
/* 위도 경도 알아오기 */
/* 첫번째 인자: 성공 시 함수 (전달 받는 매개변수는 CurrentPosition이라는 현재 위치 값)
두번째 인자: 실패 시 함수 (지금은 사용하지 않음) */
navigator.geolocation.getCurrentPosition(currentPosition => {
console.log(currentPosition);
setPosition({
latitude : currentPosition.coords.latitude,
longitude : currentPosition.coords.longitude
})
resolve(currentPosition.coords);
});
})
.then(coords => {
/* 날씨 API 요청하기 */
fetch(`https://api.openweathermap.org/data/2.5/weather?lat=${coords.latitude}&lon=${coords.longitude}&appid=${API_KEY}&lang=kr`)
.then(response => response.json())
.then(json => {
console.log(json);
setCityname(json.name);
setWeather(json.weather[0]);
setWind(json.wind);
});
});
},
[]
);
return (
<>
<h1>현재 위치</h1>
<h4>{ `위도: ${ position.latitude } 경도: ${ position.latitude }`}</h4>
<h4>{ `조회도시: ${ cityname }`}</h4>
<h4>{ `날씨: ${ weather.main } 날씨 설명: ${ weather.description }`}</h4>
<h4>{ `풍향: ${ wind.deg } 풍속: ${ wind.speed }`}</h4>
</>
);
}
위에서 작성한 예제를 async-await로 변경해서 작성
위도, 경도 알아오기
function getPosition (){
return new Promise((resolve, reject) => {
navigator.geolocation.getCurrentPosition(currentPosition => {
console.log(currentPosition);
setPosition({
latitude : currentPosition.coords.latitude,
longitude : currentPosition.coords.longitude
})
resolve(currentPosition.coords);
});
});
}
날씨 API 요청하기
function getWeather(coords){
return fetch(`https://api.openweathermap.org/data/2.5/weather?lat=${coords.latitude}&lon=${coords.longitude}&appid=${API_KEY}&lang=kr`)
.then(response => response.json())
}
위치 정보에 대한 조회가 완료된 이후 날씨 정보 api로 요청이 되어야하므로
두 가지 비동기 요청에 대한 순서를 반드시 정해서 수행해야만 한다.
useEffect (
() => {
const loadData = async () => {
const coords = await getPosition();
const result = await getWeather(coords);
setCityname(result.name);
setWeather(result.weather[0]);
setWind(result.wind);
}
loadData();
},
[]
);
전체 포켓몬 목록에 대한 api 요청
function PokemonList() {
const [pokes, setPokes] = useState([]);
useEffect(
() => {
fetch('https://pokeapi.co/api/v2/pokemon')
.then(response => response.json())
.then(pokeUser => setPokes(pokeUser.results));
//.then(pokeUser => console.log(pokeUser)); // 로그를 찍어서 받아올 데이터를 확인한다. results안에 값이 들어 있음 하단 사진 참고
},
[]
);
return (
<>
<div>
{ pokes && pokes.map(poke => <Card poke={ poke } key={ poke.name }/>) }
</div>
</>
); // 키 값 필요
key={ poke.name }
이름 속성: name속성으로 바로 꺼내올 수 있다.
No 속성 :
https://pokeapi.co/api/v2/pokemon/1/
정규 표현식을 사용해서 링크의 맨 뒤 숫자를 이용해서 꺼내온다.
/(슬러시) 뒤에 0~9 사이의 숫자가 1글자 이상 오는 패턴을 찾아온다.
const regExp = /\/[0-9]{1,}/;
정규 표현식을 이용해서 값을 꺼내온다.
url 안에 정규 표현식과 매치되는 숫자를
문자열로 슬래시 영역을 삭제하고 숫자를 가져온다.
{ poke.url.match(regExp).toString().replace('/', '') }
function Card( { poke }) {
const [data, setData] = useState();
useEffect(
() => {
fetch(poke.url)
.then(response => response.json())
.then(json => setData(json));
//.then(json => console.log(json));
}
);
const regExp = /\/[0-9]{1,}/;
return (
<div className="card">
<h4> { data && <img src={data.sprites.back_default}/> }</h4>
<div className="info">
<h2>No.{ poke.url.match(regExp).toString().replace('/', '') }</h2>
<h3>name : { poke.name } </h3>
</div>
</div>
);
}
useEffect(
() => {
fetch(poke.url)
.then(response => response.json())
.then(json => setData(json));
//.then(json => console.log(json));
}