我正在尝试执行fetch调用以返回数组,但是,当我尝试使用map函数来迭代该数组时,编译器给出了一个错误,提示无法读取未定义的属性映射(我被卡住了,我也对类似问题进行了一些研究,但无济于事。我在这里是React的新手,因此我不确定是哪个部分导致了错误。我意识到它来自我的setState函数调用。
这是我的App.js代码:
import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
class App extends Component {
constructor() {
super();
this.state={
currencies: [],
};
}
handleChange =(event) => {
let initialData = [];
const url = `http://data.fixer.io/api/latest?access_key=ea263e28e82bbd478f20f7e2ef2b309f&symbols=${event.target.value}&format=1`
console.log("the url is: " + url)
fetch(url).
then(data =>{ return data.json();})
.then(findData => {
initialData = findData.rates
console.log(initialData)
this.setState({
currencies: initialData.rates,
});
});
}
render() {
const{currencies} = this.state;
return (
<div className="App">
{ this.state.currencies.map((current) => <div> {current.rates}</div>)}
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<p>
Edit <code>src/App.js</code> and save to reload.
</p>
<h1 className="App-title"> Welcome to DKK website </h1>
<div class="dropdown">
<select id="select1" name ="currency" value={this.state.selectValue} onChange={this.handleChange}>
<option value="EUR">-- Selecting: NILL --</option>
<option value="CAD">-- Selecting: CAD --</option>
<option value="SGD">-- Selecting: SGD --</option>
<option value="AFN">-- Selecting: AFN --</option>
</select>
</div>
<button className="pressMe" > Set Button </button>
<br/>
<br/>
<a
className="App-link"
href="https://reactjs.org"
target="_blank"
rel="noopener noreferrer"
>
Learn React
</a>
</header>
</div>
);
}
}
export default App;
答案 0 :(得分:2)
您的API调用返回一个Promise基础json数据,这意味着没有数组可以映射,立即使用Object.keys
形式为Array.map函数的对象提取键。检查打击代码,以及此代码中已解决的一些问题。
import React, { Component } from "react";
class App extends Component {
state = {
loader: false,
currencies: []
};
handleChange = event => {
const val = event.target.value;
this.setState({
selectValue: val
});
};
fetchData = () => {
this.setState({
loader: true
});
let initialData = [];
const url = `http://data.fixer.io/api/latest?access_key=ea263e28e82bbd478f20f7e2ef2b309f&symbols=${
this.state.selectValue
}&format=1`;
console.log("the url is: " + url);
fetch(url)
.then(data => {
return data.json();
})
.then(findData => {
initialData = findData.rates;
this.setState({
currencies: initialData,
loader: false
});
})
.catch(err => console.log(err));
};
render() {
const { currencies, loader } = this.state;
let list = null;
if (loader) {
list = "loading...";
} else if (!loader && currencies) {
list = Object.keys(currencies).map(current => (
<div key={current}>
{current}: {currencies[current]}
</div>
));
}
return (
<div className="App">
<header className="App-header">
<p>
Edit <code>src/App.js</code> and save to reload.
</p>
<h1 className="App-title"> Welcome to DKK website </h1>
{list}
<div className="dropdown">
<select
id="select1"
name="currency"
value={this.state.selectValue}
onChange={this.handleChange}
>
<option value="EUR">-- Selecting: NILL --</option>
<option value="CAD">-- Selecting: CAD --</option>
<option value="SGD">-- Selecting: SGD --</option>
<option value="AFN">-- Selecting: AFN --</option>
</select>
</div>
<button className="pressMe" onClick={this.fetchData}>
Set Button
</button>
<br />
<br />
<a
className="App-link"
href="https://reactjs.org"
target="_blank"
rel="noopener noreferrer"
>
Learn React
</a>
</header>
</div>
);
}
}
export default App;
答案 1 :(得分:0)
您的API调用返回一个promise,这意味着没有数组map
立即结束。使用Async/Await等待API调用完成。从API返回数据后,您可以将其保存为状态。
此代码示例呈现结果。当货币选择更改时,将进行API调用。异步/等待处理诺言并将结果保存到状态。状态一改变,就通过呈现结果来做出“反应”。
API为每种货币返回不同的rates
对象。由于这些结果是不可预测的,因此Object.keys用于访问未知响应对象的名称和值。参见more on Object.keys。
您使用解构来访问this.state.currencies
,因此在组件的其余部分中可以简单地将其称为currencies
。最后,由于您将handleChange
事件附加到了select
标记中,因此不需要该按钮。
import React, { Component } from "react";
import logo from "./logo.svg";
import "./App.css";
class App extends Component {
constructor() {
super();
this.state = {
currencies: []
};
}
handleChange = event => {
this.getData(event.target.value);
};
async getData(target) {
const url = `http://data.fixer.io/api/latest?access_key=ea263e28e82bbd478f20f7e2ef2b309f&symbols=${target}&format=1`;
console.log("the url is: " + url);
let data = await fetch(url).then(data => {
return data.json();
});
this.setState({ currencies: data });
}
render() {
const { currencies } = this.state;
console.log(this.state);
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<p>
Edit <code>src/App.js</code> and save to reload.
</p>
<h1 className="App-title"> Welcome to DKK website </h1>
<div class="dropdown">
<select
id="select1"
name="currency"
value={this.state.selectValue}
onChange={this.handleChange}
>
<option value="EUR">-- Selecting: NILL --</option>
<option value="CAD">-- Selecting: CAD --</option>
<option value="SGD">-- Selecting: SGD --</option>
<option value="AFN">-- Selecting: AFN --</option>
</select>
</div>
{/* <button className="pressMe"> Set Button </button> */}
<br />
<ul>
<li>Base: {currencies.base}</li>
<li>Date: {currencies.date}</li>
<li>Timestamp: {currencies.timestamp}</li>
{/* Sometimes currencies.rates is undefined.
Use conditional rendering to prevent errors when there is no value */}
{currencies.rates && (
<li>
Rate for {Object.keys(currencies.rates)}:{" "}
{Object.values(currencies.rates)}
</li>
)}
</ul>
{/*
<a
className="App-link"
href="https://reactjs.org"
target="_blank"
rel="noopener noreferrer"
>
Learn React
</a>
*/}
</header>
</div>
);
}
}
export default App;