我是React的新手,提取时遇到问题:
我一直在做一个反应项目,根据用户选择的公司,我必须从五个不同的URL中获取。 我已经多次更改了代码,但无法正常工作。
我尝试使用componentDidMount(但是它只被调用一次,并且我想获取许多url),并使用“ while(!this.state)”忙于等待获取以获取数据,然后再分配它,等等。 / p>
获取功能:
async fetch_data() {
var sel = this.props.select;
symbol = companies[sel];
url = 'https://www.alphavantage.co/query?function=' + func + '&symbol=' + symbol + '&outputsize=' + osize + '&apikey=' + api_key;
var response = await fetch(url);
var data = await response.json();
while(!data);
this.setState({data: data, loading: false });
this.setValues();
}
设置值功能(已修剪,因此不会太长):
setValues() {
day = this.state.data["Meta Data"]["3. Last Refreshed"];
open = this.state.data["Time Series (Daily)"][day]["1. open"];
higher = this.state.data["Time Series (Daily)"][day]["2. high"];
}
渲染功能(也已修剪):
render() {
this.fetch_data();
if(this.state.loading || !this.state || !this.state.data) {
return <div>Loading :D...</div>
} else {
return (
<div>
<h2>Symbol: {symbol}</h2>
<p>Url: {url}</p>
<ul>
<li>
Open price: {open}
</li>
<li>
Higher price: {higher}
</li>
</ul>
</div>
);
}
}
当用户选择公司时,我实际上已经完成了工作,并且符号(和URL)发生了变化...
但是问题是,例如,当程序要访问this.state.data["Time Series (Daily)"][day]["1. open"];
时,它会由于获取和接收数据而崩溃。
错误提示:
Unhandled Rejection (TypeError): Cannot read property '3. Last Refreshed' of undefined:
42 | setValues() {
> 43 | day = this.state.data["Meta Data"]["3. Last Refreshed"];
| ^ 44 | open = this.state.data["Time Series (Daily)"][day]["1. open"];
45 | higher = this.state.data["Time Series (Daily)"][day]["2. high"];
应用程序并不总是崩溃,它会显示结果,但是渲染组件会继续调用this.fetch_data(),并且它崩溃是因为有时(如80%的时间)数据没有到达,我我正在尝试访问它。
答案 0 :(得分:0)
我认为这是因为您正在调用this.fetch_data();内部render() 这意味着首先您没有状态的数据,而在有数据之后您正在更新组件,因此您一次又一次地调用this.fetch_data();
看一下React组件的生命周期:https://code.likeagirl.io/understanding-react-component-life-cycle-49bf4b8674de
另一件事无需编写while(),因为您正在使用异步等待。
答案 1 :(得分:0)
此问题的原因是setState()
is asynchronous。在您的情况下,这意味着状态在这里进行了更改:
this.setState({data: data, loading: false });
在随后对this.setValues();
的调用(它本身依赖于在组件状态下定义的data
对象)上不是立即可观察到的。
这些情况的解决方案是在setState()
方法上使用第二个回调参数来运行依赖于相应状态更改的逻辑:
/* The state change will be observable when setValues() is called via
the callback */
this.setState({data: data, loading: false }, () => {
this.setValues();
});
作为组件实现的建议,请考虑修改render()
方法,以便在day
中访问open
,higher
和render()
并进行渲染。直接,而不是像看起来那样将这些值缓存到其他位置。所以尝试这样的事情:
render() {
this.fetch_data();
if(this.state.loading || !this.state || !this.state.data) {
return <div>Loading :D...</div>
} else {
/* Call to setValues() no longer needed */
const day = this.state.data["Meta Data"]["3. Last Refreshed"];
const open = this.state.data["Time Series (Daily)"][day]["1. open"];
const higher = this.state.data["Time Series (Daily)"][day]["2. high"];
return (
<div>
<h2>Symbol: {symbol}</h2>
<p>Url: {url}</p>
<ul>
<li>
Open price: {open}
</li>
<li>
Higher price: {higher}
</li>
</ul>
</div>
);
}
}
答案 2 :(得分:0)
我找到了解决方法:
只需在返回之前将if语句放在render中,然后说“符号是否已更改?如果是,则获取,否则不”。