I am working on an assignment where I need to access data from an API. Most recently, I see that my code is working to retrieve the data... but when I try to loop over the data and display to my browser... I am getting the error:
Uncaught (in promise) Error: Objects are not valid as a React child (found: object with keys {common, official, nativeName}). If you meant to render a collection of children, use an array instead.
I found similar questions on Stack Overflow... but they were using async/await and not fetch to retrieve their data.
Could someone please explain what I'm doing wrong here?
Code below:
import React, { Component } from "react";
export default class App extends Component {
constructor(props) {
super(props);
this.state = {
items: [],
isLoaded: false,
};
}
// fetches data and sets state which rerenders App
componentDidMount() {
fetch("https://restcountries.com/v3.1/all")
.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.id}>{item.name}</li>
))}
;
</ul>
</div>
);
}
}
}
CodePudding user response:
Actually the name property is also an object. Here's an example of its content.
{common: 'Malta', official: 'Republic of Malta', nativeName: {…}}
In reactJS, you can't render an object like that. You either convert it to a string using for example JSON.stringify(myobj)
or extract the attributes you want.
In this case you should probably select what you want to display like for example:
render() {
var { isLoaded, items } = this.state;
if (!isLoaded) {
return <div>Loading...</div>;
} else {
return (
<div className="App">
<ul>
{items.map((item) => (
<li key={item.id}>{item.name.common}</li>
))}
;
</ul>
</div>
);
}
}
Also I noticed your api can handle internationalization, you can handle it in react using react-intl for example.
CodePudding user response:
I think what you are trying to do is render the entire object,u cant do that, try the render each element, The second part of my answer is that you should use an asynchronous task, because you are working with a web browser.
I hope my answer guided you
CodePudding user response:
import React, { Component } from "react";
export default class App extends Component {
constructor(props) {
super(props);
this.state = {
items: [],
isLoaded: false,
};
}
// fetches data and sets state which rerenders App
componentDidMount() {
fetch("https://restcountries.com/v3.1/all")
.then((res) => res.json())
.then((json) => {
console.log(json)
this.setState({
isLoaded: true,
items: json,
}, () => {
console.log("DONE")
});
});
}
render() {
var { isLoaded, items } = this.state;
if (!isLoaded) {
return <div>Loading...</div>;
} else {
return (
<div className="App">
<ul>
{(items || []).map((item, index) => {
return <li key={index}>{item.name.common}</li>
})}
</ul>
</div>
);
}
}
}