I’m trying to fetch data from an API in my ReactJS code, but while it works perfectly in Postman with a 200 response, my code keeps throwing an error. I’ve set up the fetch request and am handling response status, but still can’t figure out why it’s failing in React. Here is my code
Error Code:
codeimport React, {Component} from "react";
const urlEndPoint = myEndPoint => "https://api.github.com/users/adhishlal"
export default class Categories extends Component {
constructor(props) {
super(props)
this.state = {
requestFailed: false
}
}
componentDidMount() {
fetch(urlEndPoint(this.props.myEndPoint))
.then(response => {
if (!response.ok) {
throw Error(response.statusText)
}
return response
})
.then(d => response.json())
.then(response => {
this.setState({
responseData: d
})
}, () =>
{
this.setState({
requestFailed: true
})
})
}
render() {
//If request is failed
if(this.state.requestFailed)
{
return <div>Request Failed</div>
}
//Waiting for data to load from Zoho
if(!this.state.responseData)
{
return <div>Loading...</div>
}
//Finally populate the data when loaded
var indents = [];
for (var i = 0; i < 10; i++) {
indents.push(
<div className="col-sm-4 col-xs-12"><div className="cr-openings">
<p className="no-margin font-color-lightGrey no-of-openings">{i+1}</p><p className="catg-openings font-color-white">{this.state.responseData.name}</p>
<p className="font-color-lightGrey city-openings no-margin">Bangalore , Chennai , Delhi NCR , Hyderabad , Mumbai</p>
</div>
</div>
);
}
return (
<section className="dotted">
<div className="dotted-bg-dark">
<div className="container padding-80-0">
<div className="row m-b-30">
{indents}
</div>
</div>
</div>
</section>
);
}
}
Explanation of Issues:
then(d => response.json())
Misuse:d => response.json()
is incorrect because the variabled
should be the response from the previous.then
. The correct syntax isresponse => response.json()
.
- State Initialization:
responseData
was not initialized inthis.state
, which may cause issues in some cases. Initializing it asnull
will prevent any potentialundefined
errors during rendering.
- Component Structure and Error Handling:
- It’s better to use
.catch()
to handle any errors at the end of the promise chain instead of using the second argument in.then
.
- It’s better to use
- Unnecessary Function Wrapping in
then
:- Instead of
then(response => {...}, () => {...})
, separating the error handler into.catch()
is preferred for better readability.
- Instead of
Corrected Code:
codeimport React, { Component } from "react";
const urlEndPoint = myEndPoint => `https://api.github.com/users/${myEndPoint || "adhishlal"}`;
export default class Categories extends Component {
constructor(props) {
super(props);
this.state = {
requestFailed: false,
responseData: null, // Initialize responseData as null
};
}
componentDidMount() {
// Call API endpoint with optional myEndPoint prop
fetch(urlEndPoint(this.props.myEndPoint))
.then(response => {
if (!response.ok) {
throw Error(response.statusText); // Throw an error if response is not ok
}
return response.json(); // Parse JSON if response is ok
})
.then(data => {
// Set the fetched data in state
this.setState({
responseData: data,
});
})
.catch(() => {
// Handle errors by setting requestFailed to true
this.setState({
requestFailed: true,
});
});
}
render() {
const { requestFailed, responseData } = this.state;
// If request failed
if (requestFailed) {
return <div>Request Failed</div>;
}
// Waiting for data to load
if (!responseData) {
return <div>Loading...</div>;
}
// Populate the data when loaded
const indents = [];
for (let i = 0; i < 10; i++) {
indents.push(
<div className="col-sm-4 col-xs-12" key={i}>
<div className="cr-openings">
<p className="no-margin font-color-lightGrey no-of-openings">{i + 1}</p>
<p className="catg-openings font-color-white">{responseData.name}</p>
<p className="font-color-lightGrey city-openings no-margin">Bangalore, Chennai, Delhi NCR, Hyderabad, Mumbai</p>
</div>
</div>
);
}
return (
<section className="dotted">
<div className="dotted-bg-dark">
<div className="container padding-80-0">
<div className="row m-b-30">
{indents}
</div>
</div>
</div>
</section>
);
}
}
Key Changes and Explanations:
- Corrected the
.then()
chain:- Changed
.then(d => response.json())
to.then(response => response.json())
.
- Changed
- Error Handling with
.catch()
:- Added
.catch()
at the end of the promise chain for better error handling.
- Added
responseData
State Initialization:- Initialized
responseData
inthis.state
tonull
to avoid potentialundefined
issues during the initial render.
- Initialized
- Key Property in the Loop:
- Added a
key={i}
to each element inindents
to ensure unique keys, which helps React efficiently update the DOM.
- Added a
myEndPoint
in URL:- Used a template literal to pass
myEndPoint
dynamically, with a fallback to"adhishlal"
ifmyEndPoint
is not provided.
- Used a template literal to pass