React : Coin Tracker, API

<angeLog/>ยท2024๋…„ 2์›” 23์ผ

REACT

๋ชฉ๋ก ๋ณด๊ธฐ
10/25
post-thumbnail

๐Ÿ’ก๋…ธ๋งˆ๋“œ์ฝ”๋” ๋‹ˆ๊ผฌ์Œค์˜ ๊ฐ•์˜๋ฅผ ๋ณด๋ฉฐ ๊ณต๋ถ€ํ•˜๋Š” ์‹œ๋ฆฌ์ฆˆ์ž…๋‹ˆ๋‹ค.

Coin Tracker

์•”ํ˜ธํ™”ํ๋“ค๊ณผ ๊ทธ ๊ฐ€๊ฒฉ์„ List ํ˜•์‹์œผ๋กœ ๋ณด์—ฌ์ฃผ๋Š” ๊ฒƒ์„ ๋ชฉํ‘œ๋กœ ํ•˜๋Š” ํ”„๋กœ์ ํŠธ.

๋ชฉํ‘œ์ˆ˜๋ฆฝ
1. ํŽ˜์ด์ง€ or ์•ฑ์— ์ ‘์† ํ–ˆ์„ ๋•Œ loading ๋ฉ”์„ธ์ง€๋ฅผ ๋ณด์—ฌ์ค€๋‹ค.
2. ์ฝ”์ธ์˜ data๋ฅผ ๊ฐ€์ ธ์˜ค๋ฉด loading ๋ฉ”์„ธ์ง€๋Š” ์ˆจ๊ธฐ๊ณ  SUPER COOL COIN LIST๋ฅผ ๋ณด์—ฌ์ค€๋‹ค.

๐Ÿ‘‰๐Ÿป์ด๋ฒˆ์— ์‚ฌ์šฉ๋œ API:coinpaprika

JSONView(์ต์Šคํ…์…˜ ๋ฐ”๋กœ๊ฐ€๊ธฐ)
ํ•ด๋‹น APIํŽ˜์ด์ง€๋Š” jsonํŒŒ์ผ์„ rowํ˜•์‹์œผ๋กœ ๋ณด์—ฌ์ฃผ๊ธฐ ๋•Œ๋ฌธ์— ์ธ๊ฐ„์ด data๋ฅผ ์ฝ๊ธฐ์— ๊ต‰์žฅํžˆ ๋ถˆํŽธํ•˜๋‹ค. chrome์„ ์ด์šฉํ•ด์„œ ๊ฐœ๋ฐœ์„ ํ•œ๋‹ค๋ฉด google์˜ ํ™•์žฅํ”„๋กœ๊ทธ๋žจ์„ ์‚ฌ์šฉํ•˜๋ฉด data ์ฝ๊ธฐ๊ฐ€ ์ˆ˜์›”ํ•ด์ง„๋‹ค.

import { useState, useEffect } from 'react';

function App() {
  
  //loading์˜ ์ดˆ๊ธฐ๊ฐ’์„ false๋กœ ์„ธํŒ…
  const [loading, setLoading] = useState(true);
  const [coins, setCoins] = useState([]);
  
  useEffect(() => {
    //fetch๋กœ api์˜ data ๊ฐ€์ ธ์˜จ ๋‹ค์Œ์—
    fetch('https://api.coinpaprika.com/v1/tickers')
      .then(
        //res๋ฅผ res.jsonํ˜•์‹์˜ ๋ฐฐ์—ด๋กœ ๋ฆฌํ„ดํ•ด๋ผ
        (res) => res.json()
      )
      //๊ทธ ๋‹ค์Œ์— json์„ coins์— ๋‹ด์•„๋ผ.
      .then((json) => setCoins(json));
    //setLoading์œผ๋กœ loading์˜ ๊ฐ’์„ false๋กœ ๋ณ€๊ฒฝ
    setLoading(false);
  }, []);
  return (
    <div>
      <h1>The Coins({coins.length})</h1>
      {loading ? (
        <strong>Loading...</strong>
      ) : (
        <ul>
          {coins.map((item) => (
            <li key={item.id}>
              {item.name}({item.symbol}): $
              {item.quotes.USD.price}
            </li>
          ))}
        </ul>
      )}
    </div>
  );
}
export default App;

๊ฒฐ๊ณผ

์‘์šฉ : SELECT๋กœ ๋งŒ๋“ค๊ธฐ

import { useState, useEffect } from 'react';

function App() {
  const [loading, setLoading] = useState(true);
  const [coins, setCoins] = useState([]);
  useEffect(() => {
    fetch('https://api.coinpaprika.com/v1/tickers')
      .then(
        (res) => res.json()
      )
      .then((json) => setCoins(json));
    setLoading(false);
  }, []);
  return (
    <div>
      <h1>The Coins({coins.length})</h1>
      {loading ? (
        <strong>Loading...</strong>
      ) : (
        <select>
          {coins.map((item) => (
            <option key={item.id}>
              {item.name}({item.symbol}): $
              {item.quotes.USD.price}
            </option>
          ))}
        </select>
      )}
    </div>
  );
}
export default App;

CODE CHAELLENGE

๋ชฉํ‘œ์ˆ˜๋ฆฝ
1. input์— ๊ธˆ์•ก์„ ์ž…๋ ฅํ•˜๊ณ ,
2. select๋กœ ์ฝ”์ธ์„ ์„ ํƒํ•˜๋ฉด
3. ๊ตฌ์ž…ํ•  ์ˆ˜ ์žˆ๋Š” ์ฝ”์ธ์˜ ๊ฐฏ์ˆ˜๋ฅผ ์ถœ๋ ฅํ•œ๋‹ค.

import { useState, useEffect } from 'react';

function App() {
  const [budget, setBudget] = useState(0);
  const [count, setCount] = useState(0);
  const [coins, setCoins] = useState([]);

  function onChange(e) {
    setBudget(e.target.value);
    let exchangeRate = Math.round(budget / 1300);
    setCount(exchangeRate / e.target.value);
  }
  function selectCoin(e) {
    let coinPrice = Number(e.target.value.split('$')[1]);
    let exchangeRate = Math.round(budget / 1300);
    setCount(exchangeRate / coinPrice);
  }
  useEffect(() => {
    fetch('https://api.coinpaprika.com/v1/tickers')
      .then((res) => res.json())
      .then((json) => setCoins(json));
  }, []);
  return (
    <div>
      <h1>The Coins({coins.length})</h1>
      <div>
        <label htmlFor="price">์˜ˆ์‚ฐ</label>
        <input
          type="number"
          id="price"
          value={budget}
          onChange={onChange}
        />
      </div>
      <select onChange={selectCoin}>
        {coins.map((item) => (
          <option key={item.id}>
            {item.name}({item.symbol}) : $
            {item.quotes.USD.price}
          </option>
        ))}
      </select>
      <div>
        <label htmlFor="count">๊ฐฏ์ˆ˜</label>
        <input
          type="number"
          id="count"
          value={count.toFixed(5)}
          disabled
        />
      </div>
    </div>
  );
}
export default App;

๊ฒฐ๊ณผ

์ˆ˜๋ฆฝํ•œ ๋ชฉํ‘œ๋Œ€๋กœ๋Š” ์ž˜ ๋‚˜์˜ค์ง€๋งŒ ๋ถ€์ž์—ฐ์Šค๋Ÿฝ๋‹ค.
ํ˜„์žฌ ์…€๋ ‰ํŠธ ๋˜์–ด์žˆ๋Š” ์˜ต์…˜์˜ ๊ฐ€๊ฒฉ์„ ๋ฐ›์•„์ค„ useState๋ฅผ ๋งŒ๋“ค๊ณ , select์—์„œ defaultValue๋กœ coins๊ฐ€ ๋นˆ๊ฐ’์ด ์•„๋‹ˆ๋ผ๋ฉด coins[0]์•ˆ์˜ price๋ฅผ state๋กœ ๋„˜๊ธฐ๋ผ๊ณ  ํ–ˆ๋‹ค.
coins๊ฐ€ null์ด ์•„๋‹ˆ๊ธฐ ๋•Œ๋ฌธ์— coins[0]์˜ ์š”์†Œ๋“ค์„ ๋ฐ›์•„ ์˜ฌ ์ˆ˜ ์žˆ์„ ์ค„ ์•Œ์•˜๋Š”๋ฐ ์ฐพ์„ ์ˆ˜ ์—†๋‹ค๊ณ  ํ•œ๋‹ค...

๋‹ค์Œ ์ง„๋„๋ฅผ ๋‚˜๊ฐ€์•ผ ํ•˜๋ฏ€๋กœ ์ด๋ฒˆ ๋ฌธ์ œ๋Š” ๊ณต๋ถ€ํ•˜๋ฉด์„œ ํ•ด๊ฒฐํ•ด ๋ณด๋Š” ๊ฒƒ์œผ๋กœ ๋งˆ๋ฌด๋ฆฌ...๐Ÿ˜ข

๋ฆฌ์—‘ํŠธ์—์„œ ์…€๋ ‰ํŠธ ๋งŒ๋“ค๋•Œ ์ž์ฃผ ์“ด๋‹ค๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ๋ฐœ๊ฒฌ!
๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์ด์šฉํ•ด์„œ ์ข€ ๋” ๋ฐœ์ „์‹œ์ผœ๋ณผ ์ˆ˜ ์žˆ์„ ๊ฒƒ ๊ฐ™๋‹ค.
๐Ÿ‘‰๐Ÿป๋””๋ฐœ์ž๋š๋”ฑ๋‹˜์˜ ๋ธ”๋กœ๊ทธ
๐Ÿ‘‰๐Ÿปreact-select

profile
์ผ๋‹จ ํ•ด๋ณผ๊ฒŒ์š”!โœ๐Ÿป

0๊ฐœ์˜ ๋Œ“๊ธ€