无法从 Axios api 调用设置类变量
我试图在 fetchScoresCall 中设置 inPlayScores 和 FinalScores 。
我可以看到它的填充方式就像在该调用中应该的那样,但一旦在该调用之外,所有数据仍然为空。
我猜我错过了一些相对简单的东西,因为我是 React 开发的新手,所以任何对我做错的事情的帮助或解释将非常感激。
import React, { PureComponent } from 'react'
import { View, Text, Easing } from 'react-native'
import TextTicker from 'react-native-text-ticker'
import { globalStyles } from '../styles/global'
export default class ScoreRunner extends PureComponent {
constructor(props) {
super(props);
initialState = {
leagues: ['NBA', 'NFL', 'NHL'],
scores: null,
};
this.state = initialState;
this.loopForFetch = this.loopForFetch.bind(this);
this.fetchScoresCall = this.fetchScoresCall.bind(this);
this.child = null;
}
componentDidMount() {
this._asyncRequest = this.loopForFetch(this.state.leagues);
}
inPlayScores = {
NBA: null,
NFL: null,
NHL: null,
}
finalScores = {
NBA: null,
NFL: null,
NHL: null,
}
loopForFetch = (leagues = ['NBA', 'NFL', 'NHL']) => {
endPoint = '';
leagues.forEach( async league => {
switch(league) {
case 'NBA':
endPoint = "basketball";
this.fetchScoresCall(league, endPoint);
break;
case 'NFL':
endPoint = "American_Football";
this.fetchScoresCall(league, endPoint);
break;
case 'NHL':
endPoint = "Ice_Hockey";
this.fetchScoresCall(league, endPoint);
break;
}
});
console.log('finalScores are null here? ');
console.log(this.finalScores);
const strStr = <>
{console.log('finalScores are null here as well?')}
{console.log(this.finalScores)}
<Text style={{color: 'green'}}>
{this.inPlayScores['NBA']}
<Text style={{color: 'red'}}>
{this.finalScores.NBA}
</Text>
{this.inPlayScores['NHL']}
<Text style={{color: 'red'}}>
{this.finalScores['NHL']}
</Text>
{this.inPlayScores['NFL']}
<Text style={{color: 'red'}}>
{this.finalScores['NFL']}
</Text>
</Text>
</>
this.setState({ scores: strStr}, function() {
// do something with new state
this.setState(this.state);
});
this.setState.scores = strStr;
}
fetchScoresCall = async (league = null, endPoint = null) => {
console.log('do we have a this.state.finalscores?');
console.log(this.finalScores);
if (league && endPoint) {
console.log('league: ' + league + ' : endpoint: ' + endPoint);
await fetch("https://www.sportsscoredatabase.com/api/v2/json/" + this.state.apiKey + "/livescore.php?s=" + endPoint, {
"method": "GET"
})
.then(response => response.json())
.then(response => {
// console.log(response);
inPlayStr = ' :::' + league + '::: In Play: ';
finalStr = ' :::' + league + '::: Final Scores: ';
response["events"].forEach(score => {
if (score["strLeague"] === league && score["intHomeScore"] && score["intAwayScore"]) {
if (!["NS", "POST", "CANC", "FT"].includes(score["strStatus"])) {
inPlayStr += " H:" + score["strHomeTeam"] + "(" + score["intHomeScore"] + ")" + " vs. A:" + score["strAwayTeam"] + "(" + score["intAwayScore"] + ") |"
} else if (["FT", "AOT"].includes(score["strStatus"])) {
finalStr += " H:" + score["strHomeTeam"] + "(" + score["intHomeScore"] + ")" + " vs. A:" + score["strAwayTeam"] + "(" + score["intAwayScore"] + ") |"
}
}
});
if (inPlayStr === ' :::' + league + '::: In Play: ') {
inPlayStr = null;
} else {
this.inPlayScores.NBA = inPlayStr;
// this.setState({inPlayScores: {"`${league}`": inPlayStr}}).bind(this);
}
if (finalStr === ' :::' + league + '::: Final Scores: ') {
finalStr = null;
} else {
this.finalScores.NBA = finalStr;
// this.setState({finalScores: {"`${league}`": finalStr}}).bind(this);
}
})
.catch(err => {
console.log(err);
});
} else {
console.log('no endpoint or leagues specified!');
}
console.log('do we have a this.state.finalscores?');
console.log(this.finalScores);
}
render(){
console.log(this.state.scores);
if (this.state.scores === null) {
// Render loading state ...
return(
<View style={globalStyles.scorestream}>
<Text style={globalStyles.scoreheader}>Live Scores</Text>
<TextTicker style={globalStyles.scoreStreamText}
duration={25000}
scrollSpeed={10000}
easing={Easing.linear}
loop
animationType = 'scroll'
bounceSpeed={0}
>
... Loading ...
</TextTicker>
</View>
)
} else {
// Render real UI ...
return(
<View style={globalStyles.scorestream}>
<Text style={globalStyles.scoreheader}>Live Scores</Text>
<TextTicker style={globalStyles.scoreStreamText}
duration={100000}
scrollSpeed={10000}
easing={Easing.linear}
loop
animationType = 'scroll'
bounceSpeed={0}
>
{this.state.scores}
</TextTicker>
</View>
)
}
}
}
如下:
LOG finalScores are null here?
LOG {"NBA": null, "NFL": null, "NHL": null}
LOG finalScores are null here as well?
LOG {"NBA": null, "NFL": null, "NHL": null}
控制台日志输出
LOG do we have a this.state.finalscores?
LOG {"NBA": " :::NBA::: Final Scores: H:Minnesota Timberwolves(116) vs. A:Phoenix Suns(125) | H:Oklahoma City Thunder(118) vs. A:Orlando Magic(102) | H:Dallas Mavericks(110) vs. A:Houston Rockets(91) | H:Los Angeles Lakers(121) vs. A:Philadelphia 76ers(126) | H:Portland Trail Blazers(96) vs. A:San Antonio Spurs(133) |", "NFL": null, "NHL": null}
I am trying to set both inPlayScores and finalScores in the fetchScoresCall.
I can see that it's populating like it should within that call but once outside that call is still null for all data.
I'm guessing I'm missing something relatively simple since I'm newish to React development so any help or explanation of what I'm doing wrong would be greatly appreciated here.
import React, { PureComponent } from 'react'
import { View, Text, Easing } from 'react-native'
import TextTicker from 'react-native-text-ticker'
import { globalStyles } from '../styles/global'
export default class ScoreRunner extends PureComponent {
constructor(props) {
super(props);
initialState = {
leagues: ['NBA', 'NFL', 'NHL'],
scores: null,
};
this.state = initialState;
this.loopForFetch = this.loopForFetch.bind(this);
this.fetchScoresCall = this.fetchScoresCall.bind(this);
this.child = null;
}
componentDidMount() {
this._asyncRequest = this.loopForFetch(this.state.leagues);
}
inPlayScores = {
NBA: null,
NFL: null,
NHL: null,
}
finalScores = {
NBA: null,
NFL: null,
NHL: null,
}
loopForFetch = (leagues = ['NBA', 'NFL', 'NHL']) => {
endPoint = '';
leagues.forEach( async league => {
switch(league) {
case 'NBA':
endPoint = "basketball";
this.fetchScoresCall(league, endPoint);
break;
case 'NFL':
endPoint = "American_Football";
this.fetchScoresCall(league, endPoint);
break;
case 'NHL':
endPoint = "Ice_Hockey";
this.fetchScoresCall(league, endPoint);
break;
}
});
console.log('finalScores are null here? ');
console.log(this.finalScores);
const strStr = <>
{console.log('finalScores are null here as well?')}
{console.log(this.finalScores)}
<Text style={{color: 'green'}}>
{this.inPlayScores['NBA']}
<Text style={{color: 'red'}}>
{this.finalScores.NBA}
</Text>
{this.inPlayScores['NHL']}
<Text style={{color: 'red'}}>
{this.finalScores['NHL']}
</Text>
{this.inPlayScores['NFL']}
<Text style={{color: 'red'}}>
{this.finalScores['NFL']}
</Text>
</Text>
</>
this.setState({ scores: strStr}, function() {
// do something with new state
this.setState(this.state);
});
this.setState.scores = strStr;
}
fetchScoresCall = async (league = null, endPoint = null) => {
console.log('do we have a this.state.finalscores?');
console.log(this.finalScores);
if (league && endPoint) {
console.log('league: ' + league + ' : endpoint: ' + endPoint);
await fetch("https://www.sportsscoredatabase.com/api/v2/json/" + this.state.apiKey + "/livescore.php?s=" + endPoint, {
"method": "GET"
})
.then(response => response.json())
.then(response => {
// console.log(response);
inPlayStr = ' :::' + league + '::: In Play: ';
finalStr = ' :::' + league + '::: Final Scores: ';
response["events"].forEach(score => {
if (score["strLeague"] === league && score["intHomeScore"] && score["intAwayScore"]) {
if (!["NS", "POST", "CANC", "FT"].includes(score["strStatus"])) {
inPlayStr += " H:" + score["strHomeTeam"] + "(" + score["intHomeScore"] + ")" + " vs. A:" + score["strAwayTeam"] + "(" + score["intAwayScore"] + ") |"
} else if (["FT", "AOT"].includes(score["strStatus"])) {
finalStr += " H:" + score["strHomeTeam"] + "(" + score["intHomeScore"] + ")" + " vs. A:" + score["strAwayTeam"] + "(" + score["intAwayScore"] + ") |"
}
}
});
if (inPlayStr === ' :::' + league + '::: In Play: ') {
inPlayStr = null;
} else {
this.inPlayScores.NBA = inPlayStr;
// this.setState({inPlayScores: {"`${league}`": inPlayStr}}).bind(this);
}
if (finalStr === ' :::' + league + '::: Final Scores: ') {
finalStr = null;
} else {
this.finalScores.NBA = finalStr;
// this.setState({finalScores: {"`${league}`": finalStr}}).bind(this);
}
})
.catch(err => {
console.log(err);
});
} else {
console.log('no endpoint or leagues specified!');
}
console.log('do we have a this.state.finalscores?');
console.log(this.finalScores);
}
render(){
console.log(this.state.scores);
if (this.state.scores === null) {
// Render loading state ...
return(
<View style={globalStyles.scorestream}>
<Text style={globalStyles.scoreheader}>Live Scores</Text>
<TextTicker style={globalStyles.scoreStreamText}
duration={25000}
scrollSpeed={10000}
easing={Easing.linear}
loop
animationType = 'scroll'
bounceSpeed={0}
>
... Loading ...
</TextTicker>
</View>
)
} else {
// Render real UI ...
return(
<View style={globalStyles.scorestream}>
<Text style={globalStyles.scoreheader}>Live Scores</Text>
<TextTicker style={globalStyles.scoreStreamText}
duration={100000}
scrollSpeed={10000}
easing={Easing.linear}
loop
animationType = 'scroll'
bounceSpeed={0}
>
{this.state.scores}
</TextTicker>
</View>
)
}
}
}
Output of console logs are as follows:
LOG finalScores are null here?
LOG {"NBA": null, "NFL": null, "NHL": null}
LOG finalScores are null here as well?
LOG {"NBA": null, "NFL": null, "NHL": null}
and
LOG do we have a this.state.finalscores?
LOG {"NBA": " :::NBA::: Final Scores: H:Minnesota Timberwolves(116) vs. A:Phoenix Suns(125) | H:Oklahoma City Thunder(118) vs. A:Orlando Magic(102) | H:Dallas Mavericks(110) vs. A:Houston Rockets(91) | H:Los Angeles Lakers(121) vs. A:Philadelphia 76ers(126) | H:Portland Trail Blazers(96) vs. A:San Antonio Spurs(133) |", "NFL": null, "NHL": null}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您需要使用
setState
告诉 React 在异步调用(本例中为 API 调用)完成之后,使用这部分新状态更新 UI。loopForFetch
方法末尾的setState
实际上是在 API 调用解决之前调用的。因此,此时的类变量inPlayScores
和finalScores
仍未更新。您可以尝试将下面的这些代码移至请求回调:在这种情况下,我仍然建议使用 React 状态而不是类变量,因为您希望它反映在 UI 上的数据类型。这样 UI 就可以对状态变化做出“反应”。
这是CodeSandbox 示例比较这两种方法。在调用
setState
之前,类变量更新不会反映在 UI 上。而使用“React state”方法时,事情有点反应性/声明性,因为状态管理和 UI 重新渲染是由 setState 处理/触发的。这个有点题外话了。但我还建议直接渲染
strStr
而不是将其保留在this.state.scores
中。You need to use
setState
to tell React to update the UI with this piece of a new state for you, after the asynchronous call (API call in this case) is done.The
setState
at the end ofloopForFetch
method is actually being called before the API call is resolved. Hence, the class variablesinPlayScores
andfinalScores
at that moment in time are still not being updated. You could try to move these codes below to the request callback:I'd still recommend using React state over class variables in this case since it's that kind of data where you want it to reflect on the UI. So that the UI could "react" to the state change.
Here's a CodeSandbox example for comparing these two approaches. The class variable update won't reflect on the UI until you call
setState
. Whereas using the "React state" approach, things are a bit reactive/declarative because the state managing and UI rerendering are handled/triggered bysetState
.This one is a bit off-topic. But I'd also recommend rendering
strStr
directly instead of keeping it inthis.state.scores
.