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>
Related
I have following code and I am trying to display the data from the object of objects. The error that I receive is TypeError: Cannot read properties of undefined. I understand that the data isn't in the format of 'array of objects', however I still don't know how to properly map it. I would appreciate some help here...
import Layout, { siteTitle } from '../components/layout';
import { useState, useEffect } from 'react'
export default function Home({ allPosts }) {
return (
<Layout home>
<Head>
<title>{siteTitle}</title>
</Head>
<section>
{Object.values(allPosts.bpi).map(({ section, idx }) => (
<li className={utilStyles.listItem} key={idx}>
{section.description}
<br />
{section.code}
<br />
</li>
))}
</section>
</Layout>
);
}
export async function getStaticProps() {
let data = [];
let error = "";
try {
const res = await fetch(
"https://api.coindesk.com/v1/bpi/currentprice.json",
);
data = await res.json();
} catch (e) {
error = e.toString();
}
return {
props: {
allPosts: data,
error,
},
};
}
Logged data: enter image description here
Object looks like this
{
"chartName": "Bitcoin",
"bpi": {
"USD": {
"code": "USD",
"symbol": "$",
"rate": "20,220.5728",
"description": "United States Dollar",
"rate_float": 20220.5728
},
"GBP": {
"code": "GBP",
"symbol": "£",
"rate": "16,896.1488",
"description": "British Pound Sterling",
"rate_float": 16896.1488
},
}
}
You don't access the USD and GBP objects. You are just getting their names. But you can access them by name like this:
<section>
{Object.values(allPosts.bpi).map((section, idx) => (
<li className={utilStyles.listItem} key={idx}>
{allPosts.bpi[section].description}
<br />
{allPosts.bpi[section].code}
<br />
</li>
))}
</section>
EDIT
It should be section.description instead of allPosts.bpi[section].description. Same for the object code.
<section>
{Object.values(allPosts.bpi).map((section, idx) => (
<li className={utilStyles.listItem} key={idx}>
{section.description}
<br />
{section.code}
<br />
</li>
))}
</section>
You are using the map method wrong.
Try this.
Object.values(allPosts.bpi).map((section, idx) => ....
I have an array when I fetch from the API by using axios get request as follows:
useEffect(async () => {
console.log("here");
let accessToken = await AsyncStorage.getItem("accessToken");
const response = await axios
.get(API_URL + "/feed", {
headers: {
Authorization: "Bearer " + accessToken,
},
})
.then((response) => {
setFeedItems([]);
setFeedItems((feedItems) => [...feedItems, ...response.data]);
setIsLoading(false);
});
}, []);
I have a custom component which is Report.js and I want to send some information from this screen to that component by using the following code:
{isLoading == false && (
<FlatList
style={{ marginLeft: 10, marginRight: 10 }}
data={feedItems}
keyExtractor={(item) => item.id}
renderItem={({ item }) => (
<Report
name="mustafa"
username="mustafa123"
responsibleInstitution="responsible"
userId={item.userId}
category={item.category}
location={item.location}
institutionId={item.institutionId}
description={item.description}
upvotes={item.upvotes}
comments={item.comments}
/>
)}
></FlatList>
The shape of the data that is coming from the API is as follows:
[
{
"id": "6228a72cfc2ce87bb0b5f908",
"userId": "61cab704ee5f9a5cc3bd844c",
"institutionId": "61cabb2da10a9147a53e6480",
"solutionId": null,
"description": "Kayıp ilanı..",
"category": "Missing",
"comments": [
{
"id": "6228c0933ab2f166af0a9d23",
"userId": "61cab704ee5f9a5cc3bd844c",
"text": "Tamam kardeş anladık",
"date": "2022-03-09T14:58:27.091+00:00"
},
{
"id": "6228c98534572422056eb565",
"userId": "61cab704ee5f9a5cc3bd844c",
"text": "Tamam kardeş anladık 3",
"date": "2022-03-09T15:36:37.256+00:00"
}
],
"upvotes": [
"61cab704ee5f9a5cc3bd844c"
],
"location": null,
"report_image_link": null,
"file": null,
"date": "2022-03-09T13:10:04.273+00:00"
},
As you can see from the data, the 'comments' field has an array of objects with id, userId, text, and date fields. Whenever I run the code, I get the following error which is caused by the comments={item.comments} line.
The error: Objects are not valid as a React child (found: object with keys {id, userId, text, date}). If you meant to render a collection of children, use an array instead.
What I want to do is that, whenever user click a button in the Report.js component, I want to open up a modal and present the comments to the user on that component. Do you think I should change my way? How can I send the comments information to the Report component? If my approach is incorrect, what should I do?
Since comments is an array of objects, you cannot pass it as a child to a Text component. Now, it depends on how you want to visualize your data. Here is a possible solution using FlatList. You could replace the rendered component with whatever suits you the best.
const dummyData = [
{
"id": "6228c0933ab2f166af0a9d23",
"userId": "61cab704ee5f9a5cc3bd844c",
"text": "Tamam kardeş anladık",
"date": "2022-03-09T14:58:27.091+00:00"
},
{
"id": "6228c98534572422056eb565",
"userId": "61cab704ee5f9a5cc3bd844c",
"text": "Tamam kardeş anladık 3",
"date": "2022-03-09T15:36:37.256+00:00"
}
]
const App = () => {
const [data, setData] = useState(dummyData);
return (
<SafeAreaView style={{ flex: 1 }}>
<View>
<FlatList
data={data}
renderItem={({item}) => {
return <Text style={{margin: 20}}>`ID: ${item.id} userId: ${item.userId} text: ${item.text} date: ${item.date}`</Text>
}}
keyExtractor={(item, index) => index.toString()}
/>
</View>
</SafeAreaView>
);
};
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>
</>
);
};
I have a problem rendering my props data
Here I'm trying to pass props to a component with mapped data from a sample data set
const weatherComponents = weatherData.items.map(weather => {
return(
<div key={weather.forecasts.area}>
<WeatherForecast
name={weather.forecasts.area}
condition={weather.forecasts.forecast}>
</WeatherForecast>
</div>
)})
return(
{weatherComponents} )
This is the component
function WeatherForecast(props) {
return(
<div>
<p>Name: {props.name}</p>
<p>Condition: {props.condition}</p>
</div>
)}
This is the sample data set
{
"area_metadata": [
{
"name": "Yishun",
"label_location": {
"latitude": 1.418,
"longitude": 103.839
}
}
],"items": [
{
"forecasts": [
{
"area": "Yishun"
"forecast" : "cloudy"
}
]}
]}
In my browser, it shows Warning: Each child in a list should have a unique "key" prop. and the data are not rendering, it only appears "Name: " without the area name from the data set. Am I mapping the data in the wrong way? Help TT
You have 2 options ... well, 3.
You need an array in "area_metadata" and "items":
1.1. The fast solution:
const weatherComponents = weatherData.items.map(weather => {
return(
<div key={weather.forecasts[0].area}>
<WeatherForecast
name={weather.forecasts[0].area}
condition={weather.forecasts[0].forecast}>
</WeatherForecast>
</div>
)
})
return({weatherComponents})
1.2 The right solution:
const weatherComponents = weatherData.items.map(weather => {
return weather.forecasts.map( casts => (
<div key={casts.area}>
<WeatherForecast
name={casts.area}
condition={casts.forecast}>
</WeatherForecast>
</div>
))
})
return({weatherComponents})
2. You do not need an array:
{
"area_metadata": [
{
"name": "Yishun",
"label_location": {
"latitude": 1.418,
"longitude": 103.839
}
}
],
"items": [
{
"forecasts": {
"area": "Yishun"
"forecast" : "cloudy"
}
}
]
}
Just replace
const weatherComponents = weatherData.items.map(weather => {
return(
<div key={weather.forecasts.area}>
<WeatherForecast
name={weather.forecasts.area}
condition={weather.forecasts.forecast}>
</WeatherForecast>
</div>
)})
return(
{weatherComponents} )
with
const weatherComponents = weatherData.items.map(weather => {
const {area, forecast} = weather.forecasts[0];
return(
<div key={area}>
<WeatherForecast
name={area}
condition={forecast}>
</WeatherForecast>
</div>
)})
return(
{weatherComponents} )
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>)