TypeError: Failed to fetch & Cannot read properties of undefined

TypeError: Failed to fetch & Cannot read properties of undefined

我正在做一个 React 项目,我的 fetch() 函数运行异常。在我之前使用它时,它工作得很好;现在我正尝试在请求中使用相同的 headers 获取不同的 URL(相同的域),该函数表现得很奇怪。我想要做的基本上是检索包含一些数据的 JSON ,将其存储在组件的属性中,然后呈现它。同时使用 Postman URL 和 headers,我完全能够很好地收到这样的响应,但在 VisualStudio 中,我得到的错误是:

There was an error: TypeError: Failed to fetch

以及:

 The above error occurred in the <MatchList> component:

    at MatchList (http://localhost:3000/static/js/bundle.js:814:5)
    at div
    at ButtonMatches (http://localhost:3000/static/js/bundle.js:258:5)
    at div
    at App

Consider adding an error boundary to your tree to customize error handling behavior.
Visit https://reactjs.org/link/error-boundaries to learn more about error boundaries.
node_modules/react-dom/cjs/react-dom.development.js:20085
There was an error: TypeError: Cannot read properties of undefined (reading 'gameArray')
src/components/ButtonMatches.js:75

这是组件“ButtonMatches.js”,它有一个在 URL:

处调用提取的方法
import React from 'react';
import reactDom from 'react-dom';
// import { MapList } from './MapList';
import { MatchList } from './MatchList';

export class ButtonMatches extends React.Component
{

    constructor(props)
    {
        super(props);

        this.state = { totalKD: 0, totalWL: 0 };

        this.data = {  

            gameArray : [],
            categoryArray : [],
            mapArray : [],
            victoryArray : [],
            killsArray : [],
            deathsArray : [],
        };

        this.fetchHaloMatches = this.fetchHaloMatches.bind(this);
    }

    async fetchHaloMatches()  
    {
        const gamertag = document.getElementById("search-recent-matches").value; // gamertag should be the string 'giafra'.

        const url1 = 'https://cryptum.halodotapi.com/games/hmcc/stats/players/'   
        const url2 = url1 + gamertag;  // url1 + 'giafra'                                           
        const url3 = `${url2}/recent-matches?page=1`;  // '.../giafra/recent-matches?page=1

        fetch(url3, {
            "method": 'GET',
            "headers": {
                        'Content-Type': 'application/json',
                        'Cryptum-API-Version': '2.3-alpha',
                        'Authorization': 'Cryptum-Token HOePLO1QYGIbelnxcQSq9y6ZXbX6MWahQZlQq1zaXQqHXEd4mWyOZ6YgaijjdCyB'
                     }
        })
        .then(response =>      
            response.json())   
        .then(res => {   
                    
            let totalKills = 0, totalDeaths = 0, totalVictories = 0, totalLosses = 0;
            for (let i=0; i< res.data.length; i++)
            {
                
                this.data.victoryArray[i] = res.data[i].victory;
                this.data.victoryArray[i] ? totalVictories++ : totalLosses++ 

                this.data.killsArray[i] = res.data[i].stats.kills;
                totalKills += this.data.killsArray[i];

                this.data.deathsArray[i] = res.data[i].stats.deaths;
                totalDeaths += this.data.deathsArray[i];

                this.data.mapArray[i] = res.data[i].details.map.name;
                this.data.categoryArray[i] = res.data[i].details.category.name;
                this.data.gameArray[i] = res.data[i].details.engine.name;

            }

            const totalKD = (totalKills / totalDeaths), totalWL = (totalVictories / totalLosses);

            this.setState(({  .
                totalKD : totalKD,
                totalWL : totalWL 
            })); 
        })  
        .catch(error => {   
            console.log("There was an error: " + error);
        });
    }


    render()
    {
        if ((this.state.totalKD || this.state.totalWL) === 0)  
        {
            return (   
                <div>
                    <form>
                        <label htmlFor="gamertag">Xbox Live Gamertag:</label>
                        <input type="search" id="search-recent-matches" name="Gamertag" placeholder="Enter a Gamertag..."></input>
                        <button type="submit" onClick={ this.fetchHaloMatches } >Search</button>
                    </form>
                </div>
                
            );
        }

        else  
        {
            return (
                <div>
                  <div>
                    <form>
                        <label htmlFor="gamertag">Xbox Live Gamertag:</label>
                        <input type="search" id="search-recent-matches" name="Gamertag" placeholder="Enter a Gamertag..."></input>
                        <button type="submit" onClick={ this.fetchHaloMatches } >Search</button>
                    </form>
                  </div>
                  
                  <MatchList recentMatches={ this.data } />
                </div> 
            );
        }
        
    }

}

这是组件 MatchList.js:

import React from "react";
import { MatchEntry } from './MatchEntry';

export class MatchList extends React.Component  {
    constructor(props)
    {
        super(props);

    }

    render()
    {
        for (let i=0; i< 1; i++)  
        {
            return(

              <MatchEntry game={this.props.data.gameArray[i]}  
                          category={this.props.data.categoryArray[i]} 
                          map={this.props.data.mapArray[i]}
                          victory={this.props.data.victoryArray[i]} 
                          kills={this.props.data.killsArray[i]} 
                          deaths={this.props.data.deathsArray[i]} 
              />
            );
        }
    }

}

但是,我认为 MatchList 组件中发生的“无法读取未定义的属性(读取 'gameArray')”会被抛出,这只是因为 ButtonMatches 组件中的 MatchList 条件渲染确实被触发了一些原因是,传递一个未定义的道具,因为该道具依赖于 fetch() 方法的正确执行以及随之而来的请求数据的正确存储。 真的坚持这个,因为在调试时,fetch() 方法中的任何断点都被忽略,并且在执行 fetch() 之后,网络请求从 Chrome 开发人员工具的网络选项卡中消失(所以我可以'不确定它是否真的失败了。

已找到解决方案。幕后发生的事情是,由于与提交表单相关的默认事件,单击“提交”按钮时网页正在刷新。这就是为什么我的网络请求在 Chrome 开发工具的网络选项卡中“消失”了。

我通过返回来继续编辑表单的呈现:

<div>
                    <form onSubmit={(event) => { event.preventDefault(); } }>
                        <label htmlFor="gamertag">Xbox Live Gamertag:</label>
                        <input type="search" id="search-recent-matches" name="Gamertag" placeholder="Enter a Gamertag..."></input>
                        <button type="submit" onClick={ this.fetchHaloMatches } >Search</button>
                    </form>
                </div>

如您所见,我不得不调用 .preventDefault() 方法。由于 window.event 现在已弃用,我发现 onSubmit 属性 returns 与提交关联的事件(class 事件)。然后我可以在该特定事件上调用 .preventDefault() 方法,从而阻止刷新。请记住将提交按钮声明为 type="submit" 否则这将不起作用。