DEV Community

Joy Lee🌻
Joy Lee🌻

Posted on • Updated on

How to make a Currency Converter

첫번째 과제는 제공된 API(https://currencylayer.com/ )에서 실시간 환율 데이터를 가져와 환율계산기를 구현하는 프로젝트였다. 4명의 팀원이 2가지 계산기를 구현하는데 2명씩 나누어 각각 1개의 계산기를 구현하기로 했다.

MainPage.jsx

const MainPage = () => {
  return (
    <Container>
      <SelectConverter />
      <TabConverter />
    </Container>
  );
};
Enter fullscreen mode Exit fullscreen mode

API 데이터 가져오기

각 계산기별로 필요한 화폐단위는 배열에 상수로 저장해서 필요할 때 불러와서 사용했다. API 주소를 fetch할 때도 상수값을 사용했다. API로 불러온 데이터 중 환율계산에 필요한 환율정보 (data.quotes)와 시간정보(data.timestamp) 를 state에 저장해주었다.

export const SELECT_CURRENCY = ['KRW', 'JPY', 'PHP'];
export const TAB_CURRENCY = ['USD', 'KRW', 'JPY', 'CAD', 'HKD', 'CNY'];

export const API_ENDPOINT = currencies =>
  `http://api.currencylayer.com/live?access_key=${KEY}&currencies=${currencies}&format=1`;
Enter fullscreen mode Exit fullscreen mode
const [apiData, setApiData] = useState({ quotes: '', date: '' });
const [isLoading, setIsLoading] = useState(true);

useEffect(() => {
  fetch(API_ENDPOINT(TAB_CURRENCY.join(',')))
    .then(res => res.json())
    .then(data => {
      setIsLoading(false);
      if (data.success)
        setApiData({
          quotes: data.quotes,
          date: data.timestamp,
        });
    });
}, [currency]);
Enter fullscreen mode Exit fullscreen mode

  • API 데이터 fetch에 실패할 경우 (apiData.quotes: false)
{
  !apiData.quotes && (
    <LoadResult>
      {isLoading ? (
        <p></p>
      ) : (
        <p className="failed">
          환율 정보를 불러올 수 없습니다. <br />
          다시 시도해주세요.
        </p>
      )}
    </LoadResult>
  );
}
Enter fullscreen mode Exit fullscreen mode
  • API 데이터 fetch에 성공할 경우 (apiData.quotes: true)
<CurrencyResult>
  <p>
    {currentTab}&nbsp;
    {apiData.quotes ? calculator(currentTab, currency) : '0'}
  </p>
  <span>기준일 :</span>
  <span className="date">{apiData.quotes && date}</span>
</CurrencyResult>
Enter fullscreen mode Exit fullscreen mode

입력값 상태 저장 (input value, select option)

Image description

input에 10자리 이하 숫자만 입력되도록 설정하고 toLocaleString으로 입력된 숫자 3자리 마다 (,) 형식 추가

FormBox.jsx

const handleType = e => {
  const pureString = e.target.value.split(',').join('');
  if (isNaN(Number(pureString))) return;
  if (pureString.length > 10) return;
  if (Number(pureString) >= 1000) {
    setInputValue(Number(pureString).toLocaleString());
  } else {
    setInputValue(pureString);
  }
};

return (
  <FormBoxContainer onSubmit={e => e.preventDefault()}>
    <input
      type="text"
      placeholder="값을 입력하세요"
      value={inputValue}
      onChange={handleType}
      onKeyUp={handleType}
    />
    {/*<select></select>*/}
  </FormBoxContainer>
);
Enter fullscreen mode Exit fullscreen mode

FormBox.jsx

저장된 화폐단위 상수값을 불러와서 select box의 각 옵션으로 추가하고 select 박스 화폐단위 선택 시, 선택된 옵션의 value값을 currency에 저장.

const handleChange = e => {
  setCurrency(e.target.value); 
  setInputValue('');
};

return (
  <FormBoxContainer onSubmit={e => e.preventDefault()}>
    {/*<input />*/}
    <select onChange={handleChange} name="current">
      {TAB_CURRENCY.map((opt, index) => (
        <option key={index} value={opt}>
          {opt}
        </option>
      ))}
    </select>
  </FormBoxContainer>
);
Enter fullscreen mode Exit fullscreen mode

탭 기능 구현

Image description
ResultBox.jsx

const [tabs, setTabs] = useState(TAB_CURRENCY);

const handleClick = (e) => {
  setCurrentTab(e.target.innerHTML);
};

useEffect(() => {
  const handleTab = () => {
    let changedTabs = TAB_CURRENCY.filter((tab) => tab !== currency);
    setTabs(changedTabs);
    setCurrentTab(changedTabs[0]);
  };
  handleTab();
}, [currency, setCurrentTab]);

  return (
    <ResultBoxContainer>
      <Tabs>
        {tabs.map((tab, index) => (
          <li key={index} onClick={handleClick}
              className={tab === currentTab ? 'active' : null}
             >
            {tab}
           </li>
        ))}
      </Tabs>
      {/*<TabResultBox>...</TabResultBox>*/}
    </ResultBoxContainer>
  );
};
Enter fullscreen mode Exit fullscreen mode
import { DateConverter } from 'utils/dateConverter';

const writtenMoney = Number(inputValue.split(',').join(''));
const date = DateConverter(apiData.date);

const calculator = (target, base) => {
  let targetRate = apiData.quotes[`USD${target}`];
  let baseRate = apiData.quotes[`USD${base}`];
  let exchangeRate = Number((targetRate / baseRate) * writtenMoney);
  return exchangeRate.toLocaleString('en', {
    maximumFractionDigits: 2,
  });
};

return (
  <ResultBoxContainer>
    {/*<Tabs>...</Tabs>*/}
    <CurrencyResult>
      <p>
        {currentTab}&nbsp;
        {apiData.quotes ? calculator(currentTab, currency) : '0'}
      </p>
      <span>기준일 :</span>
      <span className="date">{apiData.quotes && date}</span>
    </CurrencyResult>
  </ResultBoxContainer>
);
Enter fullscreen mode Exit fullscreen mode

Top comments (0)