Reputation: 19
Beginner to React and JavaScript, so forgive me if this is a simple fix.
I'm fetching data from a server and intend on parsing the response and storing elements of the response in an array which is a state variable, as I want to use variations in the state to update the page accordingly.
The issue I am having is that while using fetch(), I am able to retrieve the data from the server, but apparently I am unable to use setState() properly to assign the data to the variable. I've read that setState() is asynchronous, so your state variable might not be updated right away, and in that case I wonder if I can render the application whenever my state variable (array) is updated.
Below is my code:
import React, { Component } from 'react';
import './App.css';
class App extends Component{
constructor(props) {
super(props);
this.state = {
apiResponse: []
};
this.getData = this.getData.bind(this);
}
componentDidMount() {
this.getData();
}
getData = () => {
fetch('http://localhost:5000')
.then(results => results.json())
.then(console.log)
.then(results => this.setState({apiResponse: results}, () => {
console.log('data in state', this.state.apiResponse)
}))
.catch(err => console.error(err));
}
render() {
return (
<div className="App">
<h1>Display</h1>
<h1>{this.state.apiResponse}</h1>
<h1>Does this work?</h1>
</div>
);
}
}
export default App;
The first console.log that I run after fetch returns the appropriate JSON object, however the next console.log after returns an undefined, and {this.state.apiResponse}
does not render anything.
Upvotes: 0
Views: 1278
Reputation: 517
import React, { Component } from 'react';
import './App.css';
class App extends Component{
constructor(props) {
super(props);
this.state = {
apiResponse: []
};
this.getData = this.getData.bind(this);
}
componentDidMount() {
this.getData();
}
getData = () => {
fetch('http://localhost:5000')
.then(results => results.json())
.then(console.log)
.then(results => this.setState({apiResponse: results}))
.catch(err => console.error(err));
}
render() {
return (
<div className="App">
<h1>Display</h1>
<h1>{this.state.apiResponse &&
this.state.apiResponse.recordSets.map((singleRecord, index)=>
singleRecord.map(singleElement => <span>
{singleElement.FactoryName}</span>))}</h1>
<h1>Does this work?</h1>
</div>
);
}
}
export default App;
Upvotes: 0
Reputation: 1687
It's problem in your Chaining, Here's a answer:
The then method returns a Promise which allows for method chaining.
If the function passed as handler to then returns a Promise, an equivalent Promise will be exposed to the subsequent then in the method chain. - MDN
...
.then(console.log) // here you're not exposing any response
...
}
A remedy could be:
...
getData = () => {
fetch('http://localhost:5000')
.then(results => {console.log(results); return results.json()})
.then(results => this.setState({apiResponse: results}, () => {
console.log('data in state', this.state.apiResponse)
}))
.catch(err => console.error(err));
}
...
Upvotes: 0
Reputation: 5623
The problem is when you pass as callback to the then
consol.log
function and after what you continue with the then
chaining and expect to have access to the result, what you should do by the way is call directly the then
chain in which you set the state
before call to console.log
and then return results
in that callback like this
fetch('http://localhost:5000')
.then(results => results.json())
.then(results => {
this.setState({apiResponse: results}, () => {
console.log('data in state', this.state.apiResponse)
});
return result;
})
.then(console.log);
Or just replace it with a normal function like this
fetch('http://localhost:5000')
.then(results => results.json())
.then((results) => {
console.log(results);
return results;
})
.then(results => {
this.setState({apiResponse: results}, () => {
console.log('data in state', this.state.apiResponse)
});
return result;
});
Upvotes: 1
Reputation: 36
whenever you resolve a Promise using .then() you want to pass resolve to the next callback.
.then(console.log)
breaks that. You don't have the results in your next callback.
Read more about that here .
Upvotes: 0
Reputation: 10498
You are handling the json object with then
method but then you don't return something in order for the next then
to have as input.
If you remove this line
.then(console.log)
then it should work.
Upvotes: 1