无法从 Axios api 调用设置类变量

发布于 2025-01-16 16:04:02 字数 7403 浏览 2 评论 0原文

我试图在 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

扛刀软妹 2025-01-23 16:04:02

您需要使用 setState 告诉 React 在异步调用(本例中为 API 调用)完成之后,使用这部分新状态更新 UI。

loopForFetch 方法末尾的 setState 实际上是在 API 调用解决之前调用的。因此,此时的类变量 inPlayScoresfinalScores 仍未更新。您可以尝试将下面的这些代码移至请求回调:

// ...
.then(response => response.json())
.then(response => {
    // your logic for updating class variables...
    const strStr = <>
        <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 })
})

在这种情况下,我仍然建议使用 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 of loopForFetch method is actually being called before the API call is resolved. Hence, the class variables inPlayScores and finalScores at that moment in time are still not being updated. You could try to move these codes below to the request callback:

// ...
.then(response => response.json())
.then(response => {
    // your logic for updating class variables...
    const strStr = <>
        <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 })
})

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 by setState.

This one is a bit off-topic. But I'd also recommend rendering strStr directly instead of keeping it in this.state.scores.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文