이번 시간에는 저번에 이어서 두 번째 실습인 Coin Tracker 를 만들어 볼 것이다.
저번에 useState 실습을 해봤다면 이번엔 useEffect 실습이 될 것이다.
#7.2 Practice Coin Tracker
데이터 업로드 전 로딩 기능을 추가하고
로딩이 완료되면 코인 리스트를 쭉 보여줄 것이다.
코인 리스트는
https://api.coinpaprika.com/v1/tickers
api 이용
loading, coins 생성
const [loading, setLoading] = useState(true);
const [coins, setCoins] = useState([]);
loading : 로딩 상태 여부
coins : 코인 리스트
useEffect 로 데이터 fetch
useEffect(() => {
fetch("https://api.coinpaprika.com/v1/tickers")
.then((response) => response.json())
.then((json) => {
setCoins(json);
setLoading(false);
});
}, []);
데이터를 fetch 해서 json 데이터로 받아온 후 coins 에 저장 => setCoins 이용
데이터가 저장되었으니 loading 은 false 로 변경 => setLoading 이용
데이터는 첫 render 에 딱 한 번만 가져오면 되므로 [ ]
화면에 그려지는 부분
return (
<div>
<h1>The Coins! {loading ? "" : `(${coins.length})`}</h1>
{loading ? (
<strong>Loading...</strong>
) : (
<ul>
{
coins.map((coin, index) =>
<li key={index}>
{coin.name} ({coin.symbol}) : ${coin.quotes['USD'].price} USD
</li>)
}
</ul>
)}
</div>
);
h1 > loading 여부에 따라 coins.length 도 출력
loading === true > Loading... 출력
loading === false > ul 리스트 출력
- map 을 이용해 Bitcoin (BTC) : $51211.208097158 USD 형태로 출력
- map 을 이용하면 element 에게 key 를 줘야한다!!!! 중요
* coin.quotes['USD'].price == coin.quotes.USD.price
참고)
map 이용할 때, 괄호 주의
map(() => ( )) 의 형태가 돼야한다.
map(() => { }) 쓰면 적용 X...
전체 코드
import { useState, useEffect } from "react";
function CoinTracker() {
const [loading, setLoading] = useState(true);
const [coins, setCoins] = useState([]);
useEffect(() => {
fetch("https://api.coinpaprika.com/v1/tickers")
.then((response) => response.json())
.then((json) => {
setCoins(json);
setLoading(false);
});
}, []);
return (
<div>
<h1>The Coins! {loading ? "" : `(${coins.length})`}</h1>
{loading ? (
<strong>Loading...</strong>
) : (
<ul>
{
coins.map((coin, index) =>
<li key={index}>
{coin.name} ({coin.symbol}) : ${coin.quotes['USD'].price} USD
</li>)
}
</ul>
)}
</div>
);
}
export default CoinTracker;
#7.2.1 Practice Coin Converter - 과제
니꼬쌤 말씀대로 Converter 과제를 구현해봤다.
USD <-> BTC 처럼 Coin Converter 만들기
select 와 option 이용
select 로 여러가지 코인들의 선택지가 주어지고
선택한 코인에 따라 다른 Converter 를 보이도록 함
컴포넌트 분리
우선 선택한 option 에 따라 다른 Converter 컴포넌트를 보여야 하므로
Converter 컴포넌트를 따로 분리했다.
=> CoinConverter & Converter 두 가지로 분리 됨
CoinConverter : select 옵션에 따른 <Converter /> 표시
Converter : 실제로 Convert 를 수행하는 부분
CoinConverter
loading 이나 coins 는 CoinTracker 와 동일하게 구성
index, selected 추가
const [index, setIndex] = useState("-1");
const [selected, setSelected] = useState([]);
index : 어떤 코인을 선택했는지 식별하기 위함
selected : 선택한 코인의 정보를 가진 배열
화면에 그려지는 부분
return (
<div>
<h1>The Coin Converter {loading ? "" : `(${coins.length})`}</h1>
{loading ? (
<strong>Loading...</strong>
) : (
<div>
<select value={index} onChange={onSelect}>
<option key="-1" value="-1">Select Coin</option>
{coins.map((coin, idx) => (
<option key={idx} value={idx}>
{coin.name}
</option>
))}
</select>
<hr />
{index === "-1" ?
("Please Select Coin")
:
(<Converter coin={selected} />)
}
</div>
)}
</div>
);
ul & li 부분을 select & option 으로 변경
select 값이 변경될 때마다 onSelect 실행
idx 값을 option 의 key 로 이용
- 기본 option 은 "-1" 의 값을 갖는 Select Coin
index === "-1" > Please Select Coin 출력
index !== "-1" > Converter 출력
- coin 값으로 selected 배열을 넘겨준다.
onSelect
const onSelect = (event) => {
setIndex(event.target.value);
if (event.target.value === "-1"){
setSelected([]);
}
else {
setSelected(coins[event.target.value]);
}
}
선택한 index 로 변경 => setIndex
만약, -1 의 option 을 선택했다면 존재하지 않는 코인이므로 빈 배열로 update
그 외엔 해당 코인의 정보로 update
=> setSelected
Converter
props 받아오기
function Converter({coin}) { }
usd, disabled 생성
const [usd, setUSD] = useState(0);
const [disabled, setDisabled] = useState(false);
usd : 입력받은 값 저장
disabled : convert 는 한 방향으로 진행되어야 하므로 변환되는 값은 disabled 되도록 함
화면에 그려지는 부분
return (
<div>
<div>
<label htmlFor="USD">USD </label>
<input
id="USD"
value={
disabled ? usd * coin.quotes['USD'].price: usd
}
type="number"
onChange={onChange}
disabled={disabled}
/>
</div>
<div>
<label htmlFor={coin.symbol}>{coin.symbol} </label>
<input
id={coin.symbol}
value={disabled ? usd : usd / coin.quotes['USD'].price}
type="number"
onChange={onChange}
disabled={!disabled}
/>
</div>
<button onClick={onClick}>Convert</button>
</div>
);
disabled 값에 따라 보여지는 값과 disabled 속성을 다르게 함
자세한 내용은
2021.11.25 - [FrontEnd/React] - [ReactJS] ReactJS 로 영화 웹 서비스 만들기 (3) - Unit Converter 완성
을 참고하면 된다.
각 코인마다 다른 값을 가지므로
이름은 coin.symbol 을,
계산할 때는 coin.quotes['USD'].price 를
를 이용했다.
입력 값 => onChange
convert 버튼 => onClick
onChange, reset, onClick
const onChange = (event) => {
setUSD(event.target.value);
};
const reset = () => {
setUSD(0);
};
const onClick = () => {
reset();
setDisabled((current) => !current);
};
onChange : 입력된 값으로 update
reset : usd 값 0 으로 reset
onClick : convert 돼야 하므로 reset & setDisabled(!current)
전체 코드
import { useState, useEffect } from "react";
function Converter({coin}) {
const [usd, setUSD] = useState(0);
const [disabled, setDisabled] = useState(false);
const onChange = (event) => {
setUSD(event.target.value);
};
const reset = () => {
setUSD(0);
}
const onClick = () => {
reset();
setDisabled((current) => !current);
};
return (
<div>
<div>
<label htmlFor="USD">USD </label>
<input
id="USD"
value={
disabled ? usd * coin.quotes['USD'].price: usd
}
type="number"
onChange={onChange}
disabled={disabled}
/>
</div>
<div>
<label htmlFor={coin.symbol}>{coin.symbol} </label>
<input
id={coin.symbol}
value={disabled ? usd : usd / coin.quotes['USD'].price}
type="number"
onChange={onChange}
disabled={!disabled}
/>
</div>
<button onClick={onClick}>Convert</button>
</div>
);
}
function CoinConverter() {
const [loading, setLoading] = useState(true);
const [coins, setCoins] = useState([]);
const [index, setIndex] = useState("-1");
const [selected, setSelected] = useState([]);
useEffect(() => {
fetch("https://api.coinpaprika.com/v1/tickers")
.then((response) => response.json())
.then((json) => {
setCoins(json);
setLoading(false);
});
}, []);
const onSelect = (event) => {
setIndex(event.target.value);
if (event.target.value === "-1"){
setSelected([]);
}
else {
setSelected(coins[event.target.value]);
}
}
return (
<div>
<h1>The Coin Converter {loading ? "" : `(${coins.length})`}</h1>
{loading ? (
<strong>Loading...</strong>
) : (
<div>
<select value={index} onChange={onSelect}>
<option key="-1" value="-1">Select Coin</option>
{coins.map((coin, idx) => (
<option key={idx} value={idx}>
{coin.name}
</option>
))}
</select>
<hr />
{index === "-1" ?
("Please Select Coin")
:
(<Converter coin={selected} />)
}
</div>
)}
</div>
);
}
export default CoinConverter;
직접 과제를 구현해보니 더 유익한 시간이었다.
useState 와 useEffect 의 활용을 제대로 해볼 수 있었음
다음부턴 진짜 찐!! Movie App 구현의 시간이다.
'FrontEnd > React' 카테고리의 다른 글
[ReactJS] React Router - ReactJS 로 영화 웹 서비스 만들기 (10) (0) | 2021.12.08 |
---|---|
[ReactJS] Practice Movie App - ReactJS 로 영화 웹 서비스 만들기 (9) (0) | 2021.12.07 |
[ReactJS] Practice To Do List - ReactJS 로 영화 웹 서비스 만들기 (7) (0) | 2021.12.07 |
React 로 시계 만들기 - useState, useEffect (0) | 2021.12.04 |
[ReactJS] Effect - ReactJS 로 영화 웹 서비스 만들기 (6) (0) | 2021.12.02 |
댓글