react 초보가 쓴 글입니다! 틀린 점이 있을 수도 있어요!
노마드 코더님의 reactJs-영화 웹사이트 만들기 수업 중 코인 tracker 만드는 미니 프로젝트가 있습니다. 만드는 과정에서 보게 된 react의 상태업데이트에 대한 깨달음이 있었기에 기록합니다.
우선 저의 코드를 보여드리겠습니다.
const [coin_name,setCoinName]=useState("");
const [selected,setSelected] =useState("");
const handleChangeSelect=(e)=>{
setSelected(e.target.value);
setCoinName(selected);
console.log(coin_name);
}
return(
<div>
<h1>The Coins! ({coins.length})</h1>
{loading ? <strong>Loading ...</strong> : null}
<select onChange={handleChangeSelect} value={selected}>
{coins.map((coin
) =>
<option key={coin.name} value={coin.name}>{coin.name} ({coin.symbol}) :
${coin.quotes.USD.price }USD</option>)}
</select>
<hr/>
<p>
선택한 코인 : <b>{coin_name}</b>
</p>
<input type="number" value={dollar} onChange={handleDollar} />
<button onClick={handleClick}>변환</button>
<div>달러 코인 변환 : {result}</div>
</div>
);
제가 생각한 방향을 설명드리겠습니다.
1. 먼저 coin을 선택한다.
2. hadleSelect실행
2-1 setSelected 로 변환된 값을 저장한다.
2-2 coinName도 업데이트 해준다. = > 문제 발생💥
react에서 useState는 비동기적(Asynchronous)으로 동작합니다.
설명하자면 데이터를 한번에 모아서 처리하는 "배치"처리를 합니다.
여러개의 state를 "하나"로 모아서 처리하는 것입니다.
그렇다면 제가 실수한 것은 무엇이었을 까요?
setSelected호출한 뒤 setCoinName을 호출하는 것 -> 이게 문제였습니다!
이미 selected의 state를 변경하는 중에 coin_name까지 변경하는 것이 문제인 것입니다.
이러한 동기,비동기 문제를 해결하기 위해서는 2가지 방법이 있어요. setState로 인자를 전달하는 것과 useEffect를 사용하는 방법입니다.
다시 문제의 시작점으로 돌아오겠습니다.
구현해야 하는 것은
사용자가 자신의 dollar의 값을 입력한 뒤 선택한 coin.quotes.USD.price로 나누어 몇 개의 코인으로 바꿀 수 있을지 계산해주는 것입니다.
결과적으로 저는 value값을 처음부터 coin.quotes.USD.price로 가져오는 것을 택하였습니다.
import { useState,useEffect } from "react";
function App() {
const [loading, setLoading]=useState(true);
const [coins, setCoins] = useState([]);
const [coin_priceInUSD,setCoinPrice]=useState(0);
const [input_dollar,setDollar]=useState(0);
const [result,setResult]=useState("");
function handleSelect(event){
setCoinPrice(event.target.value);
}
const handleDollar =(e)=>{
setDollar(e.target.value);
}
const handleOperate=()=>{
setResult(input_dollar/coin_priceInUSD);
}
useEffect(()=>{
fetch("https://api.coinpaprika.com/v1/tickers")
.then((response) => response.json())
.then((json) =>
{setCoins(json);
setLoading(false);
});
},[]);
return(
<div>
<h1>The Coins! ({coins.length})</h1>
{loading ? (<strong>Loading ...</strong> ):
(
<select onChange={handleSelect}>
{coins.map((coin) => (
<option key={coin.id} value={coin.quotes.USD.price}>{coin.name} ({coin.symbol}) :
${coin.quotes.USD.price }USD</option>))}
</select>)}
<hr/>
<p>{coin_priceInUSD}</p>
<input value={input_dollar} onChange={handleDollar}></input>
<button onClick={handleOperate}>전환</button>
<p>{result}개</p>
</div>
);
}
export default App;
작동원리 입니다.
1. select를 할때 onChange로 coin의 값을 받아옵니다.
2. 사용자가 선택한 coin_price의 값을 보여줍니다.
3. 사용자가 달러의 값을 입력할 때 handleDollar로 dollar의 값을 update해줍니다.
4. 전환 버튼을 클릭하면 handleOperate를 이용하여 result를 update해줍니다.

다음과 같은 화면을 볼 수 있습니다.
다시 생각해보니 coin name은 가져올 필요가 없었고 오직 coin의 값만 알면되었기에 handle은 coin_priceinUSD로 하면 되었어요.
그리고 handledollar는 dollar의 값을 update, handleOperate는 result를 update해주면 해결될 문제였습니다.
다음엔 useState와 useEffect에 대한 기본문서도 읽어보며 정리해보는 시간을 가져보겠습니다!
읽어주셔서 감사해요😊