A simple currency converter in React does not update when the currency is changed.

huangapple go评论53阅读模式
英文:

A simple currency converter in React does not update when the currency is changed

问题

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.

这是我正在尝试构建的React中的简单货币转换器。然而,当我尝试从下拉列表中更改货币时,汇率不会更新。我认为这可能是其中一个从API获取汇率的useEffect之一的问题。但我感到困惑。

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".

这是我在控制台中收到的错误:
"react-dom.development.js:86 警告:value属性接收到NaN。如果这是预期的,请将值转换为字符串。" 和 "VM586:1 未捕获的(在promise中)SyntaxError:意外的标记 '<',"<!DOCTYPE "... 不是有效的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!

非常感谢您的帮助!

英文:

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 &#39;./App.css&#39;;
import React, { useEffect, useState } from &#39;react&#39;;
import CurrencyRow from &#39;./CurrencyRow&#39;;
const BASE_URL = &#39;https://api.exchangerate.host/latest&#39;;
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(() =&gt; {
fetch(BASE_URL)
.then((res) =&gt; res.json())
.then((data) =&gt; {
const firstCurrency = Object.keys(data.rates)[0];
setCurrencyOptions([...Object.keys(data.rates)]);
setFromCurrency(data.base);
setToCurrency(firstCurrency);
setExchangeRate(data.rates[firstCurrency]);
});
}, []);
useEffect(() =&gt; {
if (fromCurrency != null &amp;&amp; toCurrency != null) {
fetch(`$(BASE_URL)?base=${fromCurrency}&amp;symbols=${toCurrency}`)
.then((res) =&gt; res.json())
.then((data) =&gt; 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 (
&lt;&gt;
&lt;h1&gt;Convert currency&lt;/h1&gt;
&lt;CurrencyRow
currencyOptions={currencyOptions}
selectedCurrency={fromCurrency}
onChangeCurrency={(e) =&gt; setFromCurrency(e.target.value)}
onChangeAmount={handleFromAmountChange}
amount={fromAmount}
/&gt;
&lt;div className=&quot;equals&quot;&gt;=&lt;/div&gt;
&lt;CurrencyRow
currencyOptions={currencyOptions}
selectedCurrency={toCurrency}
onChangeCurrency={(e) =&gt; setToCurrency(e.target.value)}
onChangeAmount={handleToAmountChange}
amount={toAmount}
/&gt;
&lt;/&gt;
);
}
export default App;

CurrencyRow.jsx:

/* eslint react/prop-types: 0 */
import React from &#39;react&#39;;
import &#39;./App.css&#39;;
const BASE_URL = &#39;https://api.exchangerate.host/latest&#39;;
function CurrencyRow(props) {
const {
currencyOptions,
selectedCurrency,
onChangeCurrency,
amount,
onChangeAmount,
} = props;
return (
&lt;div&gt;
&lt;input
type=&quot;number&quot;
className=&quot;input&quot;
value={amount}
onChange={onChangeAmount}
/&gt;
&lt;select value={selectedCurrency} onChange={onChangeCurrency}&gt;
{currencyOptions.map((option) =&gt; (
&lt;option key={option} value={option}&gt;
{option}{&#39; &#39;}
&lt;/option&gt;
))}
&lt;/select&gt;
&lt;/div&gt;
);
}
export default CurrencyRow;

Any help will be greatly appreciated! Thanks so much!

答案1

得分: 0

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

因为 fromCurrencytoCurrency 的初始值是 undefined,但你却将它们与 null 进行比较,所以它会触发获取,因为值是 undefined 而不是 null

所以我认为你需要将 if 语句更改为以下形式:

if (!fromCurrency || !toCurrency) {
   // 进行获取和其他操作。
}

这意味着只有当你拥有两个值时才会进行获取。不接受空字符串、undefined 或 null。

英文:

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.

答案2

得分: 0

问题出在你调用 API 时使用 fromCurrency 和 toCurrency。模板文字使用错误。请使用大括号括起 BASE_URL 变量,而不是括号。将其更改为fetch(`${BASE_URL}?base=${fromCurrency}&amp;symbols=${toCurrency}`)

查看这个 Codesandbox 链接
https://codesandbox.io/s/cold-sky-us38d7?file=/src/App.js

英文:

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}&amp;symbols=${toCurrency}`)

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

huangapple
  • 本文由 发表于 2023年2月8日 17:57:44
  • 转载请务必保留本文链接:https://go.coder-hub.com/75384059.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定