React items.map is not a function when items is an array? - javascript

Loading in an API and I'm getting .map isn't a function. Been looking through every example and followed them exactly but still getting this error. The error is of course happening at the .map in the ul tag
class Login extends Component {
constructor(props) {
super(props);
this.state = {
items: [],
isLoaded: false
};
}
componentDidMount() {
fetch(
"https://opentdb.com/api.php?amount=10&category=18&difficulty=easy&type=boolean"
)
.then(res => res.json())
.then(json => {
this.setState({ isLoaded: true, items: json });
});
}
render() {
var { isLoaded, items } = this.state;
if (!isLoaded) {
return <div>Loading...</div>;
} else {
return (
<div className="App">
<ul>
{items.map(item => (
<li key={item.results.question}>{item.results.question}</li>
))}
</ul>
</div>
);
}
}
}
export default Login;

Your actual data is coming in json.results, so you need to set json.results in state like,
this.setState({ isLoaded: true, items: json.results });
You need to iterate array like,
{ items.map(item => (
<li key={item.question}>{item.question}</li>
))}
Demo

Related

Can't iterate over array in state React making an API request

I'm not sure what I'm doing wrong or what I'm missing but I can't iterate over my array of objects when I do my get request. I get the results on my console but they don't appear on the page unless I call one individual item. It only happens when I'm using React, I have also tried with JSON placeholder fake APIs and get the same result. Is there anything in React that stops this iteration to be executed? Thank you so much for your help!
import React, { Component } from 'react';
class UserList extends Component {
constructor(props) {
super(props);
this.state = {
users: [],
isLoaded: false,
};
}
componentDidMount() {
this.loadData();
}
loadData = async () => {
const response = await fetch('http://dev.pubmate.io/pubmate/api/0.1/user/all');
if (response) {
const allusers = await response.json();
console.log(response);
console.log(allusers);
console.log(allusers[0].email);
this.setState({
isLoaded: true,
users: [...allusers],
});
}
};
render() {
let { isLoaded, users } = this.state;
if (!isLoaded) {
return <div>Loading...</div>;
} else {
return (
<div className="userlist">
Data is been loaded
<ul>
{users.map((user) => {
<li key={user.id}>{user.title}</li>;
})}
</ul>
</div>
);
}
}
}
export default UserList;
You were quite close, but just need to slightly adjust your loop.
The simplest change would be to swap:
<ul>
{users.map(user => {
<li key={user.id}>
{user.title}
</li>
})}
</ul>
for
<ul>
{users.map(user => ( // <--- "{" becomes "("
<li key={user.id}>
{user.title}
</li>
))} // <--- "}" becomes ")"
</ul>
This will return an element to be rendered

Fetch data with react and componentDidMount

I try to get some data from an api but for some reason it's not working.
Normally when i try to fetch data this way it's working fine
class App extends Component {
constructor() {
super();
this.state = {
items: []
};
}
componentDidMount() {
this.getData();
}
getData() {
fetch(url)
.then(results => results.json())
.then(results => this.setState({ items: results }));
}
render() {
const {items} = this.state;
return (
<ul>
{items.map(function(item, index) {
return (
<div>
<li><h1>{console.log(item.title)}</h1></li>
</div>
);
}
)}
</ul>
);
}
}
I got this error in the browser
TypeError: items.map is not a function

After fetch state returns undefined

Im using fetch to post data to my local api, but when trying to get them and error like this occures. In fetch i get result perfectly fine, but after that trying to pass that into state like below:
this.setState({
items: result.items })
but items returns undefined and don't know why ?
My code:
class App extends Component {
constructor(props) {
super(props);
this.state = {
items: [],
error: null,
isLoaded: false
};
this.setState = this.setState.bind(this);
}
componentDidMount() {
fetch("http://localhost:3000/items")
.then(res => res.json())
.then(result => {
console.log(result);
this.setState({
items: result.items,
isLoaded: true
});
console.log(this.state.items)
},
(error) => {
this.setState({
isLoaded: true,
error
});
}
)
}
render() {
const { error, isLoaded, items } = this.state;
if (error) {
return <div>Error: {error.message}</div>;
} else if (!isLoaded) {
return <div>Loading...</div>;
} else {
return (
<ul>
<h1>Saved items:</h1>
{
items && items.map(item => (
<li key={item.name}>
item: {item.name} {item.price}
</li>
))
}
</ul>
);
}
}
}
You can do either:
this.setState({
items: result.items || [],
isLoaded: true
});
or
{
items && items.map(item => (
<li key={item.name}>
{item.name} {item.price}
</li>
))
}

JavaScript .map not rendering chrome.topSites in React

I'm trying to render a list of titles from Chrome's topSites api for a chrome extension.
When I log it to the console I get this:
[
{
"title": "Chrome Web Store",
"url": "https://chrome.google.com/webstore?hl=en"
}
]
However, the following doesn't render anything to the page
render() {
return (
<ul>
{
chrome.topSites.get(data => {
console.log(data);
data.map(site => {
return (
<li key={site.title}>
{site.title}
</li>
);
});
})
}
</ul>
);
}
Expected output:
A p tag with the title of the site gets rendered to the screen
Actual output:
Nothing is rendered on screen
This ended up working for me. Moving chrome.topSites.get intocomponendDidMount()and assigning it to state. Then mapping thethis.state.sites` to the page in the render method.
export default class TopSites extends Component {
constructor(props) {
super(props);
this.state = {
sites: [],
}
}
componentDidMount() {
chrome.topSites.get(data => {
this.setState({
sites: data
});
});
}
render() {
const {sites} = this.state;
return (
<ul>
{sites.map(site => {
return (
<li key={site.title}>
{site.title}
</li>
);
})}
</ul>
);
}
}
state= {
data: '',
}
// declaring a async function
getData = async () => {
const result = await chrome.topSites.get(); // waiting for the result
this.setState({ data: result});
}
componentDidMount(){
this.getData();
}
render(){
const list = this.state.data ? this.state.data.map((val) => <li key={val.title}> {val.title}
</li> : null)
return(
<ul>
{list}
</ul>
)
}

React - onChange function 'this.state' is undefined

I'm experimenting with React and I'm trying to create a Search to filter a list of items. I have two components, the main one displaying the list of items which calls the Search component.
I have an onChange function that sets the term in the state as the input value and then calls searchItems from the main component to filter the list of items. For some reason in searchItems, this.state is undefined. I thought adding bind to onInputChange in the Search component would sort it out but it did not make any difference. Maybe there's something I'm missing.
Main Component
import React, { Component } from 'react';
import _ from 'lodash';
import Search from './search';
class Items extends Component {
constructor(props) {
super(props);
this.state = {
error: null,
isLoaded: false,
items: []
};
}
componentDidMount() {
fetch("[url].json")
.then(res => res.json())
.then(
(result) => {
this.setState({
isLoaded: true,
items: result
});
}
),
(error) => {
this.setState({
isLoaded: true,
error
})
}
}
searchItems(term) {
const { items } = this.state;
const filtered = _.filter(items, function(item) {
return item.Name.indexOf(term) > -1;
});
this.setState({ items: filtered });
}
render() {
const { error, isLoaded, items } = this.state;
if (error) {
return <div>Error: {error.message}</div>;
}
else if (!isLoaded) {
return <div>Loading...</div>;
}
else {
return (
<div>
<Search onSearch={this.searchItems}/>
<ul>
{items.map(item => (
<li key={item.GameId}>
{item.Name}
</li>
))}
</ul>
</div>
)
}
}
}
export default Items;
Search Component
import React, { Component } from 'react';
class Search extends Component {
constructor(props) {
super(props);
this.state = {
term: ''
};
}
render() {
return (
<div>
<input type="text" placeholder="Search" value={this.state.term} onChange={event => this.onInputChange(event.target.value)} />
</div>
);
}
onInputChange(term) {
this.setState({ term });
this.props.onSearch(term);
}
}
export default Search;
You didn't bind searchItems() in the Items component.
Try changing it to an arrow function:
searchItems = () => {
// blah
}
or otherwise binding it in the constructor():
constructor() {
// blah
this.searchItems = this.searchItems.bind(this);
}
or when you call it.
You can read more about this here.

Categories