【问题标题】:Received NaN for the `value` attribute. If this is expected, cast the value to a string收到 `value` 属性的 NaN。如果这是预期的,请将值转换为字符串
【发布时间】:2021-06-27 17:47:43
【问题描述】:

我收到此错误: 1.警告:收到 value 属性的 NaN。如果这是预期的,请将值转换为字符串。 2.警告:列表中的每个孩子都应该有一个唯一的“关键”道具。 这是我的代码:

const BASE_URL = `http://api.exchangeratesapi.io/latest?access_key=${ACCESS_KEY}`

const 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, 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([data.base, ...Object.keys(data.rates)])
           setFromCurrency(data.base)
           setToCurrency(firstCurrency)
           setExchangeRate(data.rates[firstCurrency])
       })
  }, [])

  useEffect(() => {
     if (fromCurrency != null && toCurrency != null) {
       fetch(BASE_URL)
     .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</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:

const 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.id} value={option}>{option}</option>
                ))}
            </select>
        </div>
    )
}

export default CurrencyRow;

【问题讨论】:

  • data.rates[firstCurrency] 的值是多少? (在setExchangeRate(data.rates[firstCurrency]) 内)。它是string 还是number
  • option 对象是什么样的?
  • data.rates[firstCurrency] 的值来自 Api,其中值因国家/地区的货币而异。
  • 及其在api中的值为EUR=1
  • 当您定义 toAmountfromAmount 时,您可以尝试记录 typeof amountexchangeRate 吗?要知道为什么amountNaN

标签: reactjs


【解决方案1】:

好的,所以我设法重做错误,我想我已经找到了解决方案。

1.解决“value 属性的Nan”问题
在这里,您检查 fromCurrencytoCurrency 是否不为空。但实际上当你第一次渲染你的 App 组件时,fromCurrencytoCurrencyundefined (并且 undefined ≠ null):所以exchangeRate 将被设置为data.rates[undefined],即当然是undefined

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

因此,当您定义toCurrencyfromCurrency 时,您会将数字乘以或除以undefined,这就是它返回NaN 的原因:

toAmount = amount * exchangeRate // 1 * undefined → NaN

fromAmount = amount / exchangeRate // 1 / undefined → NaN

所以要解决这个问题,您可以检查fromCurrencytoCurrency 是否为null,而不是检查它们是否为undefined

if (fromCurrency !== undefined && toCurrency !== undefined) {
    // ...
}

2。解决“列表中的每个孩子都应该有一个唯一的key prop”的问题
在这里,当您通过options 进行映射时,您将每个optionkey 属性设置为option.id

{currencyOptions.map(option => (
    <option key={option.id} value={option}>{option}</option>
))}

但是如果你记录currencyOptions,你可以看到它们只是字符串(“AUD”、“CAF”、“CHF”、...),所以它们没有任何id 属性,因为它们不是对象。所以option.idundefined。但是还有另一种方法可以在每个 option 上设置一个唯一的 key 值:.map() 允许您在每次迭代中获得一个 index

<select value={selectedCurrency} onChange={onChangeCurrency}>
    {currencyOptions.map((option, index) => (
        <option key={index} value={option}>{option}</option>
    ))}
</select>

希望这能解决您的问题!

【讨论】:

  • 谢谢,键的第二个错误消失了,但值属性错误仍然存​​在..
  • @stranger 是的,我犯了一个错误,第一个问题的第一个解决方案(将fromCurrency 和`toCurrency` 设置为null)不起作用。我已经更新了我的帖子,这里是一个 [sandbox] (codesandbox.io/s/smoosh-sea-xt3ed?file=/src/App.js),问题消失了。
  • 是的...错误消失了谢谢您的帮助@pierre-lgb...我认为您在 Reactjs 方面经验丰富。你能指导我理解反应吗?如果是,请分享您的任何社交媒体帐户..
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-16
  • 1970-01-01
  • 2022-10-07
  • 2015-01-15
  • 2016-05-24
  • 2020-04-21
相关资源
最近更新 更多