Reputation: 194
I'm new to React and I'm trying to build (for now) a simple app that allows you to search for a name in a list of transactions and return the transaction details to you. So far I have been struggling to deal with the API request and I keep running into errors. I'm using superagent for my API calls
import React, {Component } from 'react';
import Request from 'superagent'
import './App.css';
class App extends Component {
constructor() {
super();
this.state = {};
}
componentWillMount() {
var url = 'https://api.myjson.com/bins/2dorw';
Request.get(url).then((response) => {
this.setState({
items: response.body.items,
});
});
}
render() {
var names = this.state.items.map((name, index) => {
<div>
<li key={index}> {this.state.items.merchant.name } </li>
</div>
});
return (
<div className="App">
{names}
</div>
);
}
}
export default App;
I can't even make this simple API call to work, just display the names from the API endpoint. This has been going on for a day or so, and usually I get the object either null, undefined and type errors.
Uncaught (in promise) TypeError: Cannot read property '_currentElement' of null(…)
App.js:64 Uncaught TypeError: Cannot read property 'map' of undefined
I have tried following tutorials but I haven't been able to find one that would work in my case, so I can't wrap my head around the API call.
UPDATE
After changing to componentDidMount(), adding isFetching and setting items to an array in setState (as the two answers have suggested), I am now getting an
Uncaught (in promise) TypeError: Cannot read property 'name' of undefined
Upvotes: 0
Views: 1939
Reputation: 5111
Using componentWillMount()
is slightly early in the lifecycle. Wait until it has mounted using componentDidMount()
That should help resolve the first error being thrown.
The second error comes from this.state.items.map
when the items
have not shown up yet. I would also suggest adding a isFetching
state, to check if the data has shown up yet.:
class App extends Component {
constructor() {
super();
this.state = {
isFetching: true
};
}
componentDidMount() {
var url = 'https://api.myjson.com/bins/2dorw';
Request.get(url).then((response) => {
this.setState({
items: response.body.items,
isFetching: false
});
});
}
render() {
if (this.state.isFetching) return null;
var names = this.state.items.map((item, index) => {
<div>
<li key={index}> {item.merchant.name} </li>
</div >
});
return (
<div className="App">
{names}
</div>
);
}
}
export default App;
Added a slight change - looks like your map function was also a bit off. It's hard to say what exactly you are looking for, because I don't know the data structure exactly.
You had
var names = this.state.items.map((name, index) => {
<div>
<li key={index}> {this.state.items.merchant.name } </li>
</div>
});
Passing name
as the first param, which is the entire item. You then call this.state all over again - which you shouldn't need to do. I think this is where some of the undefined
issues are coming from as well.
Upvotes: 1
Reputation: 1757
this.state.items
is undefined because you declared state = {}
, so can not map over it. You can fix this problem by making items an empty array.
constructor() {
super();
this.state = {
items: []
};
}
Upvotes: 0