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" 否则这将不起作用。
我正在做一个 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" 否则这将不起作用。