I am trying to display a JSON object which is an array in React. I am able to write the React code for doing that. However, I am not able to see the output in my browser.
Here is my code:
import React, {Component} from 'react';
import data from '../articles';
export default class fetchData extends Component {
showData = (inputValue) => {
inputValue.forEach((temp) => {
return (
<h1> temp.article_id </h1>
);
});
}
render () {
return (
<h1> {this.showData(data)} </h1>
);
}
}
JSON object: (located in ../articles)
[
{
"article_id": "101",
"org_id": "10001",
"reported_by": "Srilakshmi",
"reported_on": "11-16-2016",
"author": "Sree",
"language": "English",
"src_url": "",
"key_words": "CS, Programming",
"status": "Draft",
"channel_ids": "IOE1",
"title": "CS 101 Lession",
"description": "CS 101 First Lession",
"file_on_disk": "",
"publish_on": "",
"Published_on": "",
"contentArray": ""
},
{
"article_id": "102",
"org_id": "10001",
"reported_by": "Srini",
"reported_on": "11-16-2016",
"author": "Srini",
"language": "English",
"src_url": "",
"key_words": "CS, DB",
"status": "Draft",
"channel_ids": "IOE2",
"title": "CS DB 101 Lession",
"description": "CS DB 101 First Lession",
"file_on_disk": "",
"publish_on": "",
"Published_on": "",
"contentArray": ""
}
]
Any help with getting the data to display would be highly appreciated.
3 mistakes here...
First:
<h1> temp.article_id </h1> won't print article ID. Use curly braces to print actual value
<h1>{ temp.article_id }</h1>
Second:
forEach array method just loops array, it does not create new one from values returned in callback. Use map method instead.
inputValue.map((temp) => {
return (
<h1> temp.article_id </h1>
);
});
Third:
you are not returning from showData method at all.
Edit your code to return newly created array of components (that array created using map method)
showData = (inputValue) => {
return inputValue.map((temp) => {
return (
<h1>{ temp.article_id }</h1>
);
});
}
Bonus:
make it short using arrow functions
showData = (inputValue) =>
inputValue.map(temp => <h1>{ temp.article_id }</h1>)
Related
i want to show the post detail in frontend. my api is showing the postdetail like below captured in postman:
"message": "Posts fetched successfully!",
"posts": {
"_id": "61f05f676793d49f466e7aaa",
"title": "Liberal Arts Student Sample",
"content": "The three-page.",
"creator": {
"_id": "61cd99efa0b8d616a7a53ce1",
"createdAt": "2021-12-30T11:37:19.041Z",
"updatedAt": "2022-01-06T14:35:48.801Z",
"__v": 0,
"bio": "user bio",
"name": "username"
},
"Comments": [],
"created": "2022-01-25T20:36:55.095Z",
"createdAt": "2022-01-25T20:36:55.096Z",
"updatedAt": "2022-01-25T20:36:55.096Z",
"__v": 0
}
}
i want to exhibit this post detail in frontend and here is the code:
export default function PostDetail() {
const { postId } = useParams();
const post = useSelector((state) => state.post)
const dispatch = useDispatch();
const { title, content,creator, created } = post;
const fetchPostDetail = async (id) => {
const response = await axios.get(`http://localhost:5000/api/articles/post/${id}`, { post })
.catch(err => {
console.log(err);
})
dispatch(selectedPost(response.data.posts));
}
useEffect(() => {
fetchPostDetail(postId)
}, [])
return (
<div>
<h1>Post Detail</h1>
<div>
<h2>{title}</h2>
<i>posted in {created}</i>
<li>Created by {creator.map((m,i)=>(
<b key={i}>{m.name}</b>
))}</li>
<p>{content}</p>
</div>
</div>
);
}
There are three errors:
Uncaught TypeError: creator is undefined
The above error occurred in the component:
Uncaught TypeError: creator is undefined
if i mute the
Created by {creator.map((m,i)=>(
{m.name}
))} then it shows the post detail without post author name. but i want to show the author name.
how can i solve that?
thank you in advance
For the first time when the component will mount, the value of the creator will be undefined. You need to add a check before getting the nested value.
<div>
<h1>Post Detail </h1>
<div>
<h2>{title} </h2>
<i> posted in {created} </i>
{creator && <li> Created by :{creator.name}</li>}
<p> {content} </p>
</div>
</div>
Note: One thing more, Creator is not an array. it is an Object. So you cant map the object. In case it is an array, You have to make above check in that case too.
Here, creator is an Object. Whereas .map function is for Array.
To map an Object you can check:
map function for objects (instead of arrays)
You have provided your object with creater,
"creator": {
"_id": "61cd99efa0b8d616a7a53ce1",
"createdAt": "2021-12-30T11:37:19.041Z",
"updatedAt": "2022-01-06T14:35:48.801Z",
"__v": 0,
"bio": "user bio",
"name": "username"
},
map method is only works with Array. But Here You have used with Object
<div>
<h1>Post Detail</h1>
<div>
<h2>{title}</h2>
<i>posted in {created}</i>
<li>Created by {creator.map((m,i)=>(
<b key={i}>{m.name}</b>
))}
</li>
<p>{content}</p>
</div>
</div>
You can replace Your code with
<div>
<h1>Post Detail</h1>
<div>
<h2>{title}</h2>
<i>posted in {created}</i>
<li><b>Created by {creator.name}</b></li>
<p>{content}</p>
</div>
</div>
make sure the post object contains the "creator" key, and you don't need map() if the state looks exactly like the API response. If you could show how the state looks that will reveal more of the issue.
Very new to React, so I might be approaching this the wrong way... I want my app to take input from a text input field, retrieve a JSON from the reddit API (the url is built from the text input), and then render data from the JSON, looping through each of the entries. I'm using useState to trigger the data render. I can successfully retrieve the data and output specific values, but I want to be able to have a loop that dynamically outputs the data into various HTML elements.
Here's what I have so far that allows me to output some specific values as an example:
import React, { useState } from 'react';
const App = () => {
const [retrievedData, setRetrievedData] = useState([])
const runSearch = async() => {
const searchInput = document.getElementById('searchInput').value
const searchUrl = 'https://www.reddit.com/r/' + searchInput + '/new/.json?limit=5'
const response = await fetch(searchUrl)
const redditResponse = await response.json()
setRetrievedData(<>
<p>{JSON.stringify(redditResponse.data.children[0].data.author)}</p>
<p>{JSON.stringify(redditResponse.data.children[0].data.title)}</p>
</>)
}
return (
<>
<section>
<input type="text" id='searchInput' placeholder='Enter a subreddit...'></input>
<button onClick={runSearch}>
Get Data
</button>
<div>{retrievedData}</div>
</section>
</>
);
};
export default App;
And here's an example of the JSON that is retrieved from the reddit API, just stripped down with only the example values I use in my code above:
{
"kind": "Listing",
"data": {
"modhash": "",
"dist": 5,
"children": [
{
"kind": "t3",
"data": {
"author": "author1",
"title": "title1"
}
},
{
"kind": "t3",
"data": {
"author": "author2",
"title": "title2"
}
},
{
"kind": "t3",
"data": {
"author": "author3",
"title": "title3"
}
},
{
"kind": "t3",
"data": {
"author": "author4",
"title": "title4"
}
},
{
"kind": "t3",
"data": {
"author": "author5",
"title": "title5"
}
}
],
"after": "t3_jnu0ik",
"before": null
}
}
I just need the final rendered output to be something like:
<h2>TITLE 1</h2>
<h4>AUTHOR 1</h4>
<p>SELFTEXT 1</p>
...and repeated for each post data that is retrieved.
I've seen a variety of different ways to render JSON data and many of them show either loops and/or the .map() method, but I can't ever seem to get those to work, and wonder if it's an issue with the useState. Perhaps there is some way I should be rendering the data some other way?
You don't need set jsx to state, you can directly iterate children data with map
Try this
const App = () => {
const [retrievedData, setRetrievedData] = useState([])
const runSearch = async() => {
const searchInput = document.getElementById('searchInput').value
const searchUrl = 'https://www.reddit.com/r/' + searchInput + '/new/.json?limit=5'
const response = await fetch(searchUrl)
const redditResponse = await response.json()
if (redditResponse.data.children && redditResponse.data.children.length) {
setRetrievedData(redditResponse.data.children)
}
}
return (
<>
<section>
<input type="text" id='searchInput' placeholder='Enter a subreddit...'></input>
<button onClick={runSearch}>
Get Data
</button>
<div>
{
retrievedData.map((children, index) => {
return (
<div key={children.data.author + index}>
<div>Kind: { children.kind }</div>
<div>Author: { children.data.author }</div>
<div>Title: { children.data.title }</div>
</div>
)
})
}
</div>
</section>
</>
);
};
What I am trying to do is fetch the inner data of blog_set. But in my case, I'm getting a null value (usually nothing is output).
Is this the correct way to get the value: {bloglist.blog_set.title} ?
api-data:
[
{
"url": "http://localhost:8000/api/category/brown",
"id": 1,
"title": "brown",
"slug": "brown",
"image": "http://localhost:8000/media/category/bg_1.jpg",
"description": "",
"created_on": "2020-05-08T15:21:02Z",
"status": true,
"blog_set": [
{
"id": 6,
"url": "http://localhost:8000/api/blog_detail/test3",
"title": "test3",
"slug": "test3",
"image": "http://localhost:8000/media/blog/author.jpg",
"description": "test3",
"created_on": "2020-05-13T13:36:45Z",
"status": true,
"category": [
1
]
}
]
}
]
./src/Category.js
export default class App extends Component{
state = {
bloglist: [],
};
componentDidMount() {
this.fetchData();
}
fetchData = async () => {
try {
const response = await fetch("http://localhost:8000/api/category");
const jsonResponse = await response.json();
this.setState({ bloglist: jsonResponse });
} catch (error) {
console.log(error);
}
};
render(){
{
const { bloglist } = this.state;
return(
<div>
{bloglist.map((bloglist) => (
<div>
<h3 class="mb-2">{bloglist.blog_set.title}</h3>
</div>
))}
</div>
);
}
}
}
blog_set is an array so it does not have an attribute/memeber/item called title. You should define at what index you want the data.
bloglist.blog_set[0].title
Or iterate over blog_set too
As bloglist is also an array you need to use one more .map() or as bloglist[0].blog_set[0].title
Example:
{bloglist.map((bloglist) => (
<div>
<h3 class="mb-2">{bloglist.blog_set.map(i=> i.title)}
</h3>
</div>
))}
blogList.map() will iterate the parent Array of objects to get blog_set and blog_set.map() will now iterate the blog_set to get list title
{bloglist.map((bloglist) =>(
<div>
<h3 class="mb-2">{bloglist.blog_set.map((list)=>( list.title)}</h3>
</div>)}
blog_set is an array. In order to iterate it, use map and {title}. In each iteration of your blog_set object, there is a key named title (destructured object).
<div>
{bloglist.map((bloglist) => (
<div>
<h3 class="mb-2">{blog_set.map(({title})=>title))}</h3>
</div>
))}
</div>
I have facing an issue in React js, I want to render all data from rest API and show with a numeric index.
Rest API:
[
{
"id": "1",
"start_date": "2020-05-08 09:45:00",
"end_date": "2020-05-08 10:00:00",
"full_name": "mirza",
"cust_full_name": "furqan",
},
{
"id": "2",
"start_date": "2020-05-08 02:45:00",
"end_date": "2020-05-08 03:00:00",
"full_name": "mirza",
"cust_full_name": "ahmed",
},
{
"id": "3",
"start_date": "2020-05-08 06:45:00",
"end_date": "2020-05-08 07:00:00",
"full_name": "mirza",
"cust_full_name": "ali",
}
]
my code:
render()
{
let FullNameSlot1 = null //FullNameSlot
let SecondFullNameSlot1 = null
let BaberNameSlot1 = null //BaberNameSlot
let SecondBaberNameSlot1 = null
if (this.state.appointmentdata && this.state.appointmentdata.length
this.state.appointmentdata[0].start_date.toString() > this.state.newprevious
)
{
FullNameSlot1 = (
<p key={0}>{this.state.appointmentdata[0].cust_full_name}</p>
)
BaberNameSlot1 = (
<p key={0}>{this.state.appointmentdata[0].full_name}</p>
)
}
i want to render data with array {index}
if (this.state.appointmentdata && this.state.appointmentdata.length
this.state.appointmentdata[1].start_date.toString() > this.state.newprevious
)
{
SecondFullNameSlot1 = (
<p key={1}>{this.state.appointmentdata[1].cust_full_name}</p>
)
SecondBaberNameSlot1 = (
<p key={1}>{this.state.appointmentdata[1].full_name}</p>
)
}
I want to render all data from rest API and show with a numeric index. Make my code it simple.
<p key={index}>{this.state.appointmentdata[index][0].cust_full_name}</p>
<p key={index}>{this.state.appointmentdata[index][1].cust_full_name}</p>
Demo:
https://codesandbox.io/s/agitated-elion-quqp1
What should i do? Any one help me?
You can use conditional rendering and your final condition is a ternary to either map the array of data to JSX or return null. The array::map first argument is the current element being iterated, and the second argument is the current index. When returning JSX like this though you need to return a single node. Here I've used a react Fragment and attached the key there. I also destructured the element properties you wanted to display.
Conditional Rendering
Lists and Keys
{
(this.state.appointmentdata &&
this.state.appointmentdata.length &&
this.state.appointmentdata[1].start_date.toString() > this.state.newprevious)
? this.state.appointmentdata.map(({ cust_full_name, full_name }, index) => (
<Fragment key={index}>
<p>{cust_full_name}</p>
<p>{full_name}</p>
</Fragment>
) : null
}
#adnan khan Welcome to Stackoverflow! to render an array of elements you can make use of Array.map function https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map
In your example it might look like this
if(this.state.appointmentdata && this.state.appointmentdata.length){
this.state.appointmentdata.map((data ,index) => <p key={index}>{data.cust_full_name}</p> )
}
If you want to render elements dynamically then conditional rendering is an option
You can use map() on appointmentdata and create the same number of elements as objects in the result of API
Sample:
render() {
return (
<React.Fragment>
{
this.state.appointmentdata.length
?
this.state.appointmentdata.map(ele => {
return (
<React.Fragment>
<p key={`cf_${ele.id}`}>{ele.cust_full_name}</p>
<p key={`f_${ele.id}`}>{ele.full_name}</p><hr/>
</React.Fragment>
)
})
: "__"
}
</React.Fragment>
);
}
I'm new to React-Native and I'm learning this by tutorials and examples all over the web. I am trying to do something very simple but it has been a week since I hit this problem and after digging StackOverflow and many other contents, none of them could help. So I decided to ask it directy. My apologies if the question looks duplicate or it seems silly.
I am trying to iterate over a JSON object and display it. All I want to do right now is to show each JSON object with its title (username). I'm planning to do much more - make the title a button and show the details of user after hitting button - but right now this is the big rock I've hit into.
Here is my code. Please note my comment on fetchdata method :
import React, { Component } from 'react'
import { View, Text, FlatList, TouchableOpacity, ListView } from 'react-native'
class MyListItem extends React.PureComponent {
_onPress = () => {
this.props.onPressItem(this.props.id);
};
render() {
const textColor = this.props.selected ? "red" : "black";
return (
<TouchableOpacity onPress={this._onPress}>
<View>
<Text style={{ color: textColor }}>
{this.props.title}
</Text>
</View>
</TouchableOpacity>
);
}
}
export default class HttpExample extends Component {
constructor(props) {
super(props);
this.state = {
data: '',
username: [],
first_name: '',
last_name: ''
};
//Using ES6 we need to bind methods to access 'this'
this.fetchData = this.fetchData.bind(this);
}
componentDidMount() {
this.fetchData();
}
fetchData() {
// The first line - which is commented - returns all of non-admin
// users, the second one returns only one user. Note that the
// second one works fine and the first one does not.
// fetch('http://URL/users.json', {
fetch('http://URL/users/12345678001.json', {
method: 'GET'
})
.then((response) => response.json())
.then((responseJson) => {
console.log(responseJson);
this.setState({
data: responseJson,
username: responseJson.username,
first_name: responseJson.first_name,
last_name: responseJson.last_name
})
})
.catch((error) => {
console.error(error);
});
}
_keyExtractor = (item, index) => item.id;
_onPressItem = (id: string) => {
// updater functions are preferred for transactional updates
this.setState((state) => {
// copy the map rather than modifying state.
const selected = new Map(state.selected);
selected.set(id, !selected.get(id)); // toggle
return {selected};
});
};
_renderItem = ({item}) => (
<MyListItem
id={item}
onPressItem={this._onPressItem}
title={this.state.username}
/>
);
render() {
return (
<FlatList
data={[this.state.data]}
renderItem={this._renderItem}
/>
)
}
}
And here is a sample of one of my JSON objects created by Django ReST framework, written by myself. I've just simplified the object a bit and removed some of the fields, for better reading (The avatar field is a base64 image field and it is much smaller than the original one):
{
"username": "12345678003",
"email" : "sample#gmail.com",
"first_name": "AAA",
"last_name": "BBB",
"phone_number": "12045678000",
"gender": "M",
"city": "NY",
"description": "",
"date_of_birth": "2010-03-28",
"avatar": "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAkGBxAPBhAREQ8QDQ8PDxIWEBAWFRANDxAQFRUWFhURExUYHSggGBolGxUTITEhJSkrLi4uFx8zODMsNygtLisBCgoKBQUFDgUFDisZExkrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrK//AABEIAOEA4QMBIgACEQEDEQH/xAAbAAEAAgMBAQAAAAAAAAAAAAAABAUBAgMGB//EADIQAQABAwEHAQYEBwAAAAAAAAABAgMRBAUSITFBUXFhIjKRobHBM4HR8RMjQmJyguH/xAAVAQEBAAAAAAAAAAAAAAAAAAAAAf/EABQRAQAAAAAAAAAAAAAAAAAAAAD/2gAMAwEAAhEDEQA/APpgCIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADDIAAAAAAAAAAAAAAAAAAAAAAANrduaq8RGZkGqVY0FdXON2PXn8E/SaOKIzPGrv0jwlAhW9nURHHNU/B3p0tER7sOwDjVpaJj3YcbmzqJjhmJTAFPf0FdPGPaj5/BEejRtV",
"groups": [1,2],
"user_permissions": [],
"interests": [1,2]
}
The above is what I get by calling http://URL/users/12345678001.json which returns one user. I have been able to show the user as one touchable opacity in the application (the above code works) But when I call users.json which has a structure like below:
[{user1 data},{user2 data}, etc.]
I cannot make the mobile application display each user's username in the mobile output. Either I get nothing (nothing is displayed) or the usual errors pop up (TypeError: object is not a function, etc.) I want to have the application iterate through the whole users.json and show each user's username as one touchable opacity. I've tried using .map which throws me the error, or calling each object in responseJson by their array index which either shows me nothing or throws error.
Let me know about your ideas and solutions.
FYI, I am testing this on my Nexus 5X phone directly.
Update
Here is an example of users.json as it reflects in my console log :
[{
"username": "12345678001",
"email" : "sample#gmail.com",
"first_name": "AAA",
"last_name": "BBB",
"phone_number": "12045678000",
"gender": "M",
"city": "NY",
"description": "",
"date_of_birth": "2010-03-28",
"avatar": "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAkGBxAPBhAREQ8QDQ8PDxIWEBAWFRANDxAQFRUWFhURExUYHSggGBolGxUTITEhJSkrLi4uFx8zODMsNygtLisBCgoKBQUFDgUFDisZExkrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrK//AABEIAOEA4QMBIgACEQEDEQH/xAAbAAEAAgMBAQAAAAAAAAAAAAAABAUBAgMGB//EADIQAQABAwEHAQYEBwAAAAAAAAABAgMRBAUSITFBUXFhIjKRobHBM4HR8RMjQmJyguH/xAAVAQEBAAAAAAAAAAAAAAAAAAAAAf/EABQRAQAAAAAAAAAAAAAAAAAAAAD/2gAMAwEAAhEDEQA/APpgCIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADDIAAAAAAAAAAAAAAAAAAAAAAANrduaq8RGZkGqVY0FdXON2PXn8E/SaOKIzPGrv0jwlAhW9nURHHNU/B3p0tER7sOwDjVpaJj3YcbmzqJjhmJTAFPf0FdPGPaj5/BEejRtV",
"groups": [1,2],
"user_permissions": [],
"interests": [1,2]
},
{
"username": "12345678003",
"email" : "sample#gmail.com",
"first_name": "AAA",
"last_name": "BBB",
"phone_number": "12045678003",
"gender": "M",
"city": "NY",
"description": "",
"date_of_birth": "2010-12-20",
"avatar": "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAkGBxAPBhAREQ8QDQ8PDxIWEBAWFRANDxAQFRUWFhURExUYHSggGBolGxUTITEhJSkrLi4uFx8zODMsNygtLisBCgoKBQUFDgUFDisZExkrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrK//AABEIAOEA4QMBIgACEQEDEQH/xAAbAAEAAgMBAQAAAAAAAAAAAAAABAUBAgMGB//EADIQAQABAwEHAQYEBwAAAAAAAAABAgMRBAUSITFBUXFhIjKRobHBM4HR8RMjQmJyguH/xAAVAQEBAAAAAAAAAAAAAAAAAAAAAf/EABQRAQAAAAAAAAAAAAAAAAAAAAD/2gAMAwEAAhEDEQA/APpgCIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADDIAAAAAAAAAAAAAAAAAAAAAAANrduaq8RGZkGqVY0FdXON2PXn8E/SaOKIzPGrv0jwlAhW9nURHHNU/B3p0tER7sOwDjVpaJj3YcbmzqJjhmJTAFPf0FdPGPaj5/BEejRtV",
"groups": [1,2],
"user_permissions": [],
"interests": [1,2]
}]
Another Update
As requested, here is a screenshot of my console, note that it differs from what I've posted here and has many different fields :
More Investigation:
I decided to make the code much simpler, and just focus on the main problem. How to return the iterated object for display:
My code is now this:
import React, { Component } from 'react'
import { View, Text, ListView } from 'react-native'
export default class HttpExample extends Component {
constructor(props) {
super(props);
data = [''];
}
fetchData() {
fetch('http://URL/users.json', {
method: 'GET'
})
.then((response) => response.json())
.then((responseJson) => {
console.log("ResponseJson is :" + responseJson);
console.log(responseJson.users.length);
console.log(responseJson.users.username);
console.log(responseJson.users);
console.log("THIS:::" + responseJson.users[0].username);
responseJson.users.map((user) =>
{
console.log("THIS:::" + user.username);
data.push(user.username);
console.log("This.data:" + data[0] + "second:" + data[1]);
});
return data;
})
.catch((error) => {
console.error(error);
});
}
_keyExtractor = (item, index) => item.id;
render() {
return (
<View>
<ListView
dataSource={this.fetchData()}
renderRow={(data) => <Text>{data.username}</Text>}
/>
</View>
)
}
}
All of the "console.log" commands return with correct info (Check the end of the post), but my render does not work and throws undefined is not a object. I really don't understand what is the exact problem? isn't data an array? Why it can't be displayed and throws TypeError? What am I getting wrong?
console.log outputs, in correct order :
ResponseJson is :[object Object]
3
undefined
(whole users.json is returned)
THIS:::12345678001
THIS:::12345678001
This.data:second:12345678001
THIS:::12345678002
This.data:second:12345678001
THIS:::12345678003
This.data:second:12345678001