英文:
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 './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!
答案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.
因为 fromCurrency
和 toCurrency
的初始值是 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}&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}&symbols=${toCurrency}`)
Check out this Codesandbox link
https://codesandbox.io/s/cold-sky-us38d7?file=/src/App.js
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论