skip to Main Content

I am trying to build a simple currency converter in React. However, when I try to change the currencies from the drop-down, the rates do not update. I suppose it will be a problem with one of the useEffects which fetch the rates from an API. But I’m lost.

These are the errors I’m getting in the console:
"react-dom.development.js:86 Warning: Received NaN for the value attribute. If this is expected, cast the value to a string." and "VM586:1 Uncaught (in promise) SyntaxError: Unexpected token ‘<‘, "<!DOCTYPE "… is not valid JSON"

My code:

App.js:

import './App.css';
import React, { useEffect, useState } from 'react';
import CurrencyRow from './CurrencyRow';

const BASE_URL = 'https://api.exchangerate.host/latest';

function App() {
  const [currencyOptions, setCurrencyOptions] = useState([]);
  const [fromCurrency, setFromCurrency] = useState();
  const [toCurrency, setToCurrency] = useState();
  const [exchangeRate, setExchangeRate] = useState();
  const [amount, setAmount] = useState(1);
  const [amountInFromCurrency, setAmountInFromCurrency] = useState(true);

  let toAmount;
  let fromAmount;

  if (amountInFromCurrency) {
    fromAmount = amount;
    toAmount = amount * exchangeRate;
  } else {
    toAmount = amount;
    fromAmount = amount / exchangeRate;
  }

  useEffect(() => {
    fetch(BASE_URL)
      .then((res) => res.json())
      .then((data) => {
        const firstCurrency = Object.keys(data.rates)[0];
        setCurrencyOptions([...Object.keys(data.rates)]);
        setFromCurrency(data.base);
        setToCurrency(firstCurrency);
        setExchangeRate(data.rates[firstCurrency]);
      });
  }, []);

  useEffect(() => {
    if (fromCurrency != null && toCurrency != null) {
      fetch(`$(BASE_URL)?base=${fromCurrency}&symbols=${toCurrency}`)
        .then((res) => res.json())
        .then((data) => setExchangeRate(data.rates[toCurrency]));
    }
  }, [fromCurrency, toCurrency]);

  function handleFromAmountChange(e) {
    setAmount(e.target.value);
    setAmountInFromCurrency(true);
  }

  function handleToAmountChange(e) {
    setAmount(e.target.value);
    setAmountInFromCurrency(false);
  }

  return (
    <>
      <h1>Convert currency</h1>
      <CurrencyRow
        currencyOptions={currencyOptions}
        selectedCurrency={fromCurrency}
        onChangeCurrency={(e) => setFromCurrency(e.target.value)}
        onChangeAmount={handleFromAmountChange}
        amount={fromAmount}
      />
      <div className="equals">=</div>
      <CurrencyRow
        currencyOptions={currencyOptions}
        selectedCurrency={toCurrency}
        onChangeCurrency={(e) => setToCurrency(e.target.value)}
        onChangeAmount={handleToAmountChange}
        amount={toAmount}
      />
    </>
  );
}

export default App;

CurrencyRow.jsx:

/* eslint react/prop-types: 0 */

import React from 'react';
import './App.css';

const BASE_URL = 'https://api.exchangerate.host/latest';

function CurrencyRow(props) {
  const {
    currencyOptions,
    selectedCurrency,
    onChangeCurrency,
    amount,
    onChangeAmount,
  } = props;

  return (
    <div>
      <input
        type="number"
        className="input"
        value={amount}
        onChange={onChangeAmount}
      />
      <select value={selectedCurrency} onChange={onChangeCurrency}>
        {currencyOptions.map((option) => (
          <option key={option} value={option}>
            {option}{' '}
          </option>
        ))}
      </select>
    </div>
  );
}

export default CurrencyRow;

Any help will be greatly appreciated! Thanks so much!

2

Answers


  1. I couldn’t fully debug your code but I think that the problem will happen in the second useEffect in the if statement.

    because the init value of fromCurrency & toCurrency is undefined but you’re comparing it with null so it will fetch anyway because the value is undefined not Null

    so I think you need to change the if statement to be like that

    if (!fromCurrency || !toCurrency) {
       // do fetch and the rest here.
    }
    

    and that means that you will not make the fetch unliss you have two values. no empty strings, undefined or null is accepted.

    Login or Signup to reply.
  2. The issue is when you are calling the API with fromCurrency and toCurrency. The template literal is wrong. Wrap the BASE_URL variable in curly brackets, not in parentheses. Change it to fetch(`${BASE_URL}?base=${fromCurrency}&symbols=${toCurrency}`)

    Check out this Codesandbox link
    https://codesandbox.io/s/cold-sky-us38d7?file=/src/App.js

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search