class Home extends Component {
constructor(props) {
super(props);
this.state = {
data: [],
isLoaded: false,
};
}
componentDidMount() {
fetch("https://reqres.in/api/users?page=2")
.then((res) => res.json())
.then((json) => {
this.setState({
isLoaded: true,
data: json,
});
});
}
render() {
var { isLoaded, data }= this.state;
if(!isLoaded){
return<div>Is isLoaded</div>
}
else{
return (
<div>
<ul>
{() =>
this.state.data.map((data, index) => (
<li key={index}>Email: {data.email}</li>
))
}
;
</ul>
</div>
);
}
}
}
export default Home;
Hii All , I know this question is asked many times but I cant figure it out I'am getting the error. I have checked for all the questions similar to this but haven't found specific solution if I use another link i.e, "https://jsonplaceholder.typicode.com/users" this one the code works fine .
The returned data from https://reqres.in/api/users?page=2 is not an array, but an object with a data property containing what you are looking for (an array). The result of the request is :
{"page":1,"per_page":6,"total":12,"total_pages":2,"data":[{"id":1,"email":"george.bluth#reqres.in","first_name":"George","last_name":"Bluth","avatar":"https://reqres.in/img/faces/1-image.jpg"},{"id":2,"email":"janet.weaver#reqres.in","first_name":"Janet","last_name":"Weaver","avatar":"https://reqres.in/img/faces/2-image.jpg"},{"id":3,"email":"emma.wong#reqres.in","first_name":"Emma","last_name":"Wong","avatar":"https://reqres.in/img/faces/3-image.jpg"},{"id":4,"email":"eve.holt#reqres.in","first_name":"Eve","last_name":"Holt","avatar":"https://reqres.in/img/faces/4-image.jpg"},{"id":5,"email":"charles.morris#reqres.in","first_name":"Charles","last_name":"Morris","avatar":"https://reqres.in/img/faces/5-image.jpg"},{"id":6,"email":"tracey.ramos#reqres.in","first_name":"Tracey","last_name":"Ramos","avatar":"https://reqres.in/img/faces/6-image.jpg"}],"support":{"url":"https://reqres.in/#support-heading","text":"To keep ReqRes free, contributions towards server costs are appreciated!"}}
So you cannot use map function, which is from the Array prototype, on the result of your request. You must access the data property first :
this.state.data.data.map((data, index) => ( // note the double data
<li key={index}>Email: {data.email}</li>
))
You could also assign json.data to the state.data to avoid the ugly .data.data :
this.setState({
isLoaded: true,
data: json.data, // note the .data
});
I think the problem is in brackets around your .map() method. Please try this
class Home extends Component {
constructor(props) {
super(props);
this.state = {
data: [],
isLoaded: false,
};
}
componentDidMount() {
fetch("https://reqres.in/api/users?page=2")
.then(res => res.json())
.then(json => {
this.setState({
isLoaded: true,
data: json,
});
});
}
render() {
const { isLoaded, data } = this.state;
if (!isLoaded) {
return <div>Is isLoaded</div>;
} else {
return (
<div>
<ul>
{data?.map((data, index) => {
return <li key={index}>Email: {data.email}</li>;
})}
</ul>
</div>
);
}
}
}
export default Home;
I don't see any error, it's working just fine.
Output:
Working Example: StackBlitz
import * as React from 'react';
import { Text, View, StyleSheet } from 'react-native';
import Constants from 'expo-constants';
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
data: [],
isLoaded: false,
};
}
componentDidMount() {
fetch('https://reqres.in/api/users?page=2')
.then((res) => res.json())
.then((json) => {
console.log(json.data);
this.setState({
isLoaded: true,
data: json.data,
email: null,
});
});
}
render() {
var { isLoaded, data } = this.state;
if (!isLoaded) {
return <div>Is isLoaded</div>;
} else {
return (
<div>
<div className="contents home">
<img
src="https://trucard.io/india/wp-content/uploads/2021/08/2021-June-TruCard-Logo.png
"
width={50}
alt="img"
className="trucard-img"
/>
</div>
<div className="button">
<button className="button-button">Load list</button>
</div>
<ul>
{this.state.data?.map((data, index) => (
<li key={index}>Email: {data.email}</li>
))}
;
</ul>
</div>
);
}
}
}
export default App;
So the goal is to fetch data from the google books API, which returns JSON data in the same form as my state shows. I want to update title with the title string returned by the JSON data. Right now I get a "failed to compile" on the line I've marked in the code. Then, I would like to pass the title as a props to the List component, which would render it as a list item with each map through. So if 20 books' data are fetched, I would render 20 different titles. I'm new to react so I'm not sure how much is wrong here.
import React, { Component } from 'react';
import List from './List.js';
export default class Main extends Component {
state ={
items : [{
volumeInfo : {
title : "",
}
}]
}
componentDidMount() {
fetch(`https://www.googleapis.com/books/v1/volumes?q=flowers+inauthor:keyes&key=AIzaSyAWQ0wFzFPQ3YHD_uLDC7sSs-HPRM3d__E`)
.then(res => res.json())
.then(
(result) => {
this.setState({
items : [{
volumeInfo : {
title : result.items.map((book) => {
const name = book.volumeInfo.title;
return name;
})
}
}] });
})
}
render() {
return (
<div>
<header>
<h2>Google Book Search</h2>
</header>
<List title={this.state.items}/>
</div>
)
}
}
Here's List.js
import React, { Component } from 'react'
export default class List extends Component {
render() {
return (
<div>
<ul>
<li>{this.props.items}</li>
</ul>
</div>
)
}
}
As the result of your fetch() has the same structure as your items property of the state, all you need to do in the then() callback is to set the result in the state directly as shown below:
componentDidMount() {
fetch('your/long/url')
.then(res => res.json())
.then((result) => {
this.setState({ items: (result.items || []) });
});
}
Now that your state is updated with the needed data, you need to pass it as a prop to your List component:
render() {
return (
<div>
<header>
<h2>Google Book Search</h2>
</header>
<List items={ this.state.items } />
</div>
);
}
Finally, in your List component, you can make use of this prop by rendering it in a map() call:
render() {
return (
<div>
<ul>
{ this.props.items.map((book, i) => (
<li key={ i }>{ book.volumeInfo.title }</li>
)) }
</ul>
</div>
);
}
export default class Main extends Component {
state ={
items : []
}
componentDidMount() {
fetch(`https://www.googleapis.com/books/v1/volumes?q=flowers+inauthor:keyes&key=AIzaSyAWQ0wFzFPQ3YHD_uLDC7sSs-HPRM3d__E`)
.then(res => res.json())
.then((result) => {
const titleList = result.items.map((item)=>{return item.volumeInfo.title});
this.setState({items: titleList})
})
};
render(){
const {items} = this.state;
const titleComponent = items.length > 0
? items.map((item)=>{
return <List title={item} />
})
: null;
return (
<div className="App">
<header>
<h2>Google Book Search</h2>
</header>
{titleComponent}
</div>
)
}
}
Above code should be worked if your List component is working fine.
Change the setState function with this
this.setState({
items : [{
volumeInfo : {
title : result.items.map((book) => {
const name = book.volumeInfo.title;
return name;
})
}
}] });
Looks like brackets was the issue.
I am able to fetch REST API where I can get nested json output, and I want them to display in React component. Now I only can render them in the console which is not my goal actually. I am wondering if there is an efficient way to do this for rendering nested json list in React. can anyone give me a possible idea to make this work?
here is what I did:
import React, { Component } from "react";
class JsonItem extends Component {
render() {
return <li>
{ this.props.name }
{ this.props.children }
</li>
}
}
export default class List extends Component {
constructor(props){
super(props)
this.state = {
data: []
}
};
componentDidMount() {
fetch("/students")
.then(res => res.json())
.then(json => {
this.setState({
data: json
});
});
}
list(data) {
const children = (items) => {
if (items) {
return <ul>{ this.list(items) }</ul>
}
}
return data.map((node, index) => {
return <JsonItem key={ node.id } name={ node.name }>
{ children(node.items) }
</JsonItem>
});
}
render() {
return <ul>
{ this.list(this.props.data) }
</ul>
}
}
<script src="https://facebook.github.io/react/js/jsfiddle-integration-babel.js"></script>
<div id="container">
<!-- This element's contents will be replaced with your component. -->
</div>
my current output:
in my above component, I could render nested list on the console like this:
[![enter image description here][1]][1]
desired output:
how can I properly render out nested json output on React? Any idea to make this happen? any thought? Thanks
As you knew .map() is the common solution for this. But you can make this much better like below.
export default class List extends Component {
constructor(props){
super(props)
this.state = {
data: [],
isLoaded: false, //initally the loading state is false.
}
};
componentDidMount() {
fetch("/students")
.then(res => res.json())
.then(json => {
//updating the loading state and data.
this.setState({data: json, isLoaded:true});
});
}
render() {
//Waiting ajax response or ajax not yet triggered.
if(!this.state.isLoaded){
return(<div>Loading...</div>);
}else{
//Rendering the data from state.
let studenDetails = this.state.data.map((student, i) => {
let uin = student.uin;
let studentInfo = Object.keys(student.studentInfo).map((label, i) => {
return (
<div key={i}>
<span>
<strong>{label}: </strong>{`${student.studentInfo[label]}`}
</span>
</div>
);
});
return (
<div key={i}>
<h3>{uin}</h3>
<p>{studentInfo}</p>
</div>
);
});
return (<div>{studenDetails}</div>);
}
}
}
Hope it will help you.
To render a list in react use the .map() function to build a list of jsx elements.
render() {
let myRenderedData = this.state.data.map((x, index) => {
return <p key={index}>{x.uin}</p>
})
return (<div>{myRenderedData}</div>)
}
The code is hitting my endpoint, and I have received errors that indicate that it is aware of the elements inside of the list. However, the list returns a size of zero. I'm wondering if I'm passing around the state of the array incorrectly, thus why it's empty by the time I try to render it? I'm a bit of a noob to ReactJS, so excuse the silly question.
Below is the code
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.state = {
error: null,
isLoaded: false,
items: []
};
}
componentDidMount() {
fetch("http://localhost:8080/retrieve/123")
.then(res => res.json())
.then(
(res) => {
this.setState({
isLoaded: true,
items: Array.from(res)
});
},
(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>
// {items.map(item => (
// <li key={item.name}>
// {item.name} {item.price}
// </li>
// ))}
// </ul>
<div>
test{this.items},
{items.length}
</div>
);
}
}
}
ReactDOM.render(
<MyComponent />,
document.getElementById('root')
);
The items.length in the render returns a 0 and 'test' prints as well. CORS is enabled.
thank you
I am new with React and cannot write correct code for the situation. Let me explain in the code
class Test extends React.Component {
render() {
// IndexedDB indexes
const ids = ['id1', 'id2', 'id3'];
// fetch data and build a list
const files = ids.map((id) =>
localforage.getItem(id).then((entry) =>
<li key={entry.id}><img src={entry.data} /></li>
);
);
return (
<ul>{files}</ul>
)
}
}
What is the correct way to asynchronous load all data and display it?
You could do the asynchronous logic in the componentDidMount hook and use setState to put the entries in your state.
Example
class Test extends React.Component {
state = { entries: [] };
componentDidMount() {
const ids = ["id1", "id2", "id3"];
Promise.all(ids.map(id => localforage.getItem(id))).then(entries => {
this.setState({ entries });
});
}
render() {
return (
<ul>
{this.state.entries.map(entry => (
<li key={entry.id}>
<img src={entry.data} />
</li>
))}
</ul>
);
}
}