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

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

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:

  1. import './App.css';
  2. import React, { useEffect, useState } from 'react';
  3. import CurrencyRow from './CurrencyRow';
  4. const BASE_URL = 'https://api.exchangerate.host/latest';
  5. function App() {
  6. const [currencyOptions, setCurrencyOptions] = useState([]);
  7. const [fromCurrency, setFromCurrency] = useState();
  8. const [toCurrency, setToCurrency] = useState();
  9. const [exchangeRate, setExchangeRate] = useState();
  10. const [amount, setAmount] = useState(1);
  11. const [amountInFromCurrency, setAmountInFromCurrency] = useState(true);
  12. let toAmount;
  13. let fromAmount;
  14. if (amountInFromCurrency) {
  15. fromAmount = amount;
  16. toAmount = amount * exchangeRate;
  17. } else {
  18. toAmount = amount;
  19. fromAmount = amount / exchangeRate;
  20. }
  21. useEffect(() => {
  22. fetch(BASE_URL)
  23. .then((res) => res.json())
  24. .then((data) => {
  25. const firstCurrency = Object.keys(data.rates)[0];
  26. setCurrencyOptions([...Object.keys(data.rates)]);
  27. setFromCurrency(data.base);
  28. setToCurrency(firstCurrency);
  29. setExchangeRate(data.rates[firstCurrency]);
  30. });
  31. }, []);
  32. useEffect(() => {
  33. if (fromCurrency != null && toCurrency != null) {
  34. fetch(`${BASE_URL}?base=${fromCurrency}&symbols=${toCurrency}`)
  35. .then((res) => res.json())
  36. .then((data) => setExchangeRate(data.rates[toCurrency]));
  37. }
  38. }, [fromCurrency, toCurrency]);
  39. function handleFromAmountChange(e) {
  40. setAmount(e.target.value);
  41. setAmountInFromCurrency(true);
  42. }
  43. function handleToAmountChange(e) {
  44. setAmount(e.target.value);
  45. setAmountInFromCurrency(false);
  46. }
  47. return (
  48. <>
  49. <h1>Convert currency</h1>
  50. <CurrencyRow
  51. currencyOptions={currencyOptions}
  52. selectedCurrency={fromCurrency}
  53. onChangeCurrency={(e) => setFromCurrency(e.target.value)}
  54. onChangeAmount={handleFromAmountChange}
  55. amount={fromAmount}
  56. />
  57. <div className="equals">=</div>
  58. <CurrencyRow
  59. currencyOptions={currencyOptions}
  60. selectedCurrency={toCurrency}
  61. onChangeCurrency={(e) => setToCurrency(e.target.value)}
  62. onChangeAmount={handleToAmountChange}
  63. amount={toAmount}
  64. />
  65. </>
  66. );
  67. }
  68. export default App;

CurrencyRow.jsx:

  1. /* eslint react/prop-types: 0 */
  2. import React from 'react';
  3. import './App.css';
  4. const BASE_URL = 'https://api.exchangerate.host/latest';
  5. function CurrencyRow(props) {
  6. const {
  7. currencyOptions,
  8. selectedCurrency,
  9. onChangeCurrency,
  10. amount,
  11. onChangeAmount,
  12. } = props;
  13. return (
  14. <div>
  15. <input
  16. type="number"
  17. className="input"
  18. value={amount}
  19. onChange={onChangeAmount}
  20. />
  21. <select value={selectedCurrency} onChange={onChangeCurrency}>
  22. {currencyOptions.map((option) => (
  23. <option key={option} value={option}>
  24. {option}{' '}
  25. </option>
  26. ))}
  27. </select>
  28. </div>
  29. );
  30. }
  31. 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:

  1. import &#39;./App.css&#39;;
  2. import React, { useEffect, useState } from &#39;react&#39;;
  3. import CurrencyRow from &#39;./CurrencyRow&#39;;
  4. const BASE_URL = &#39;https://api.exchangerate.host/latest&#39;;
  5. function App() {
  6. const [currencyOptions, setCurrencyOptions] = useState([]);
  7. const [fromCurrency, setFromCurrency] = useState();
  8. const [toCurrency, setToCurrency] = useState();
  9. const [exchangeRate, setExchangeRate] = useState();
  10. const [amount, setAmount] = useState(1);
  11. const [amountInFromCurrency, setAmountInFromCurrency] = useState(true);
  12. let toAmount;
  13. let fromAmount;
  14. if (amountInFromCurrency) {
  15. fromAmount = amount;
  16. toAmount = amount * exchangeRate;
  17. } else {
  18. toAmount = amount;
  19. fromAmount = amount / exchangeRate;
  20. }
  21. useEffect(() =&gt; {
  22. fetch(BASE_URL)
  23. .then((res) =&gt; res.json())
  24. .then((data) =&gt; {
  25. const firstCurrency = Object.keys(data.rates)[0];
  26. setCurrencyOptions([...Object.keys(data.rates)]);
  27. setFromCurrency(data.base);
  28. setToCurrency(firstCurrency);
  29. setExchangeRate(data.rates[firstCurrency]);
  30. });
  31. }, []);
  32. useEffect(() =&gt; {
  33. if (fromCurrency != null &amp;&amp; toCurrency != null) {
  34. fetch(`$(BASE_URL)?base=${fromCurrency}&amp;symbols=${toCurrency}`)
  35. .then((res) =&gt; res.json())
  36. .then((data) =&gt; setExchangeRate(data.rates[toCurrency]));
  37. }
  38. }, [fromCurrency, toCurrency]);
  39. function handleFromAmountChange(e) {
  40. setAmount(e.target.value);
  41. setAmountInFromCurrency(true);
  42. }
  43. function handleToAmountChange(e) {
  44. setAmount(e.target.value);
  45. setAmountInFromCurrency(false);
  46. }
  47. return (
  48. &lt;&gt;
  49. &lt;h1&gt;Convert currency&lt;/h1&gt;
  50. &lt;CurrencyRow
  51. currencyOptions={currencyOptions}
  52. selectedCurrency={fromCurrency}
  53. onChangeCurrency={(e) =&gt; setFromCurrency(e.target.value)}
  54. onChangeAmount={handleFromAmountChange}
  55. amount={fromAmount}
  56. /&gt;
  57. &lt;div className=&quot;equals&quot;&gt;=&lt;/div&gt;
  58. &lt;CurrencyRow
  59. currencyOptions={currencyOptions}
  60. selectedCurrency={toCurrency}
  61. onChangeCurrency={(e) =&gt; setToCurrency(e.target.value)}
  62. onChangeAmount={handleToAmountChange}
  63. amount={toAmount}
  64. /&gt;
  65. &lt;/&gt;
  66. );
  67. }
  68. export default App;

CurrencyRow.jsx:

  1. /* eslint react/prop-types: 0 */
  2. import React from &#39;react&#39;;
  3. import &#39;./App.css&#39;;
  4. const BASE_URL = &#39;https://api.exchangerate.host/latest&#39;;
  5. function CurrencyRow(props) {
  6. const {
  7. currencyOptions,
  8. selectedCurrency,
  9. onChangeCurrency,
  10. amount,
  11. onChangeAmount,
  12. } = props;
  13. return (
  14. &lt;div&gt;
  15. &lt;input
  16. type=&quot;number&quot;
  17. className=&quot;input&quot;
  18. value={amount}
  19. onChange={onChangeAmount}
  20. /&gt;
  21. &lt;select value={selectedCurrency} onChange={onChangeCurrency}&gt;
  22. {currencyOptions.map((option) =&gt; (
  23. &lt;option key={option} value={option}&gt;
  24. {option}{&#39; &#39;}
  25. &lt;/option&gt;
  26. ))}
  27. &lt;/select&gt;
  28. &lt;/div&gt;
  29. );
  30. }
  31. 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 语句更改为以下形式:

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

这意味着只有当你拥有两个值时才会进行获取。不接受空字符串、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

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

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:

确定