Trouble getting into json data object - json

I have some code that allows the user to click a image to then update the page and display the clicked on champions name. the json data looks like this -http://ddragon.leagueoflegends.com/cdn/10.16.1/data/en_US/champion/Alistar.json
I console.log response.data and see a object of objects and am wondering how to get passed the section that has the response.data.(whatever champion the user picked). I have tried adding a variable like response.data.champion but I assume no variables can be passed like that seeing how it doesnt work.
Not sure if its even worth posting the code but just in case! My code is below, the fetch im trying to go through is in NewChamp function.
To make my request simpler, All i want to know for example is how i would get response.data.(whatever the user clicked).key from any possible champion clicked like http://ddragon.leagueoflegends.com/cdn/10.16.1/data/en_US/champion/Alistar.json or http://ddragon.leagueoflegends.com/cdn/10.16.1/data/en_US/champion/Anivia.json
or whatever other champion the user clicks.
import React, { Component } from 'react';
import './Champions.css';
class AllChamps extends Component {
render() {
let champion = this.props.champion;
return(
<div className='champions'>
<h1> all champions</h1>
{Object.keys(this.props.champions).map((s) => (
<div className='champs' onClick={() => this.props.NewChamp({s, champion})}>
<img
alt='Champion Images'
src={`http://ddragon.leagueoflegends.com/cdn/10.16.1/img/champion/${s}.png`}
onClick={this.props.onClick}
></img>
{s}
</div>
))}
</div>
)}}
class SpecificChamp extends Component {
render() {
let champion = this.props.champion
let Spec = champion[champion.length - 1];
return (
<div className='champions'>
<h1> 1 champions</h1>
<div className='champs'>
<button onClick={this.props.onClick}></button>
{Spec}
</div>
</div>
)}
}
class Champions extends Component {
constructor(props) {
super(props);
this.handleAllChamps = this.handleAllChamps.bind(this);
this.handleSpecificChamp = this.handleSpecificChamp.bind(this);
this.NewChamp = this.NewChamp.bind(this);
this.state = {
champions: [],
champion: [],
clickedChamp: false,
thisChamp: 'ahri'
}}
NewChamp = (props) =>
{
let s = props.s;
props.champion.push(s);
fetch(`http://ddragon.leagueoflegends.com/cdn/10.16.1/data/en_US/champion/${s}.json`)
.then(response => { return response.json() })
.then((response) => {
Object.keys(response.data).map((a) => (s = a
))})
fetch(`http://ddragon.leagueoflegends.com/cdn/10.16.1/data/en_US/champion/${s}.json`)
.then(response => { return response.json() })
.then((response) => {
console.log(s)
console.log(response.data)
console.log(props.champion)
})
console.log(`http://ddragon.leagueoflegends.com/cdn/10.16.1/data/en_US/champion/${s}.json`);
}
handleAllChamps = (props) => {
this.setState({ clickedChamp: true,
})};
handleSpecificChamp = () => {
this.setState({ clickedChamp: false,
})};
componentDidMount(props) {
const apiUrl = `http://ddragon.leagueoflegends.com/cdn/10.16.1/data/en_US/champion.json`;
fetch(apiUrl)
.then(response => { return response.json() })
.then((response) => {
this.setState({
champions: response.data
}, () => (this.state.champions))
return
})
}
render() {
const clickedChamp = this.state.clickedChamp;
let display;
if (clickedChamp ) {
display = <SpecificChamp champion={this.state.champion} onClick={this.handleSpecificChamp} s={this.state.thisChamp}/>;
} else {
display = <AllChamps champions={this.state.champions} onClick={this.handleAllChamps} NewChamp={this.NewChamp} thisChamp={this.state.thisChamp} champion={this.state.champion} />;
}
return (
<div>
<div className='champions'></div>
{display}
</div>
);
}
}
export default Champions;

Your response is in the form of Object of Objects. You've to use JSON.stringify(response.data) in order to view the entire data as a string in the debug console.
You will have to destructure the Object of objects.
Object.keys(response.data).map((key)=> console.log(response.data[key]))
In this case if it is just one key
response.data[s]

Related

React rendering JSON nested objects

I have this code which works perfectly:
componentDidMount() {
fetch('https://services2.arcgis.com/sJvSsHKKEOKRemAr/arcgis/rest/services/Bigfoot%20Locations/FeatureServer/0/query?where=1%3D1&outFields=*&outSR=4326&f=json')
.then((response) => {
return response.json();
})
.then((myJson) => {
this.setState({data: myJson.features[0].attributes.STATE_NAME})
console.log(this.state.data)
});
}
render() {
return (
<div className = ''>
{this.state.data}
</div>
)
}
}
However when I try to make the data set in state more general so that I can render whatever I want like this:
componentDidMount() {
fetch('https://services2.arcgis.com/sJvSsHKKEOKRemAr/arcgis/rest/services/Bigfoot%20Locations/FeatureServer/0/query?where=1%3D1&outFields=*&outSR=4326&f=json')
.then((response) => {
return response.json();
})
.then((myJson) => {
this.setState({data: myJson.features})
console.log(this.state.data)
});
}
render() {
return (
<div className = ''>
{this.state.data[0].attributes.STATE_NAME}
</div>
)
}
}
I get "Cannot read property STATE_NAME of undefined. The only change is that I tried to access the object in the render method instead of ComponentDidMount. What's the issue here?
In your component, the render() function is being called before the data is populated, even though componentDidMount() will run before the first render.
What you need is to store an intermediate loading state in your react state to indicate that the data has not yet arrived.
class RENAME_ME extends Component {
state = {
loaded: false,
data: [],
};
componentDidMount() {
fetch(
"https://services2.arcgis.com/sJvSsHKKEOKRemAr/arcgis/rest/services/Bigfoot%20Locations/FeatureServer/0/query?where=1%3D1&outFields=*&outSR=4326&f=json"
)
.then((response) => {
return response.json();
})
.then((myJson) => {
this.setState({
data: myJson.features[0].attributes.STATE_NAME,
loaded: true,
});
console.log(this.state.data);
});
}
render() {
// Data is still loading, display an intermediate message
if (!this.state.loaded) {
return <p>Loading...</p>;
}
return <div className="">{this.state.data}</div>;
}
}
You shouldn't read from the state until it's present:
render() {
return (
<div className = ''>
{(this.state.data && this.state.data.length) ? this.state.data[0].attributes.STATE_NAME : `still loading, or maybe an error`}
</div>
)
}
Only display the state when it is present so this condition has 2 parts.
First part(this.state.data) is only true when the data is saved in the state so the next part(this.state.data[0].attributes.STATE_NAME) runs after that
render() {
return (
<div className = ''>
{this.state.data && this.state.data[0].attributes.STATE_NAME}
</div>
)
}
}
Your state 'data' is not properly initialized to handle object maybe
are they initialized like this?
this.state = {
data: []
You can render the value whenever it is present by
{this.state.data[0].attributes && this.state.data[0].attributes.STATE_NAME}

how to fetch array of objects from json

This is the api http://skunkworks.ignitesol.com:8000/books/ ,
I am trying to fetch the array results from it using the fetch method but instead get an error cannot fetch value of undefined
import React, { Component } from 'react';
class App extends Component {
constructor() {
super()
this.state = {
books: []
}
}
componentDidMount() {
fetch('http://skunkworks.ignitesol.com:8000/books/')
.then(res => res.json())
.then(data => this.setState({ books: data }))
.catch(e => {
console.log(e);
return e;
});
}
render() {
let book = []
book = this.state.books.results;
console.log(book[0])
return (
<div>
<h1>Books</h1>
</div>
)
}
}
export default App;
this is my code.
Also I have observed that json data are usually like [{}] but here it is {} format.
please suggest me some solution.....
As I see from your url link, you json array of data is present in the results key of the returned object from the API.
So if you're only interested by the results you should do something like that :
import React, { Component } from 'react';
class App extends Component {
state = {
books: []
}
async componentDidMount() {
const objectFromUrl = await fetch('http://skunkworks.ignitesol.com:8000/books/')
const data = await objectFromUrl.json() //first way
// or you can use destructuring way
const { results } = await objectFromUrl.json() //second way
this.setState({
books: data.results // results key contains your '[{}]' data an array of objects
})
}
render() {
const { books } = this.state
return (
<div>
<h1>Books</h1>
{books.map(book => (
<h2> {book.id} </h2>
)}
</div>
);
}
// You can use destructuring again to get only key you're interested by
render() {
const { books } = this.state
return (
<div>
<h1>Books</h1>
{books.map(({id, formats}) => (
<h2> {id} </h2>
<h2> { formats[ˋapplication/pdf’] } </h2>
)}
</div>
);
}
}

TypeError: items is undefined while reading a json using fetch in reactjs

This is the first time I'm working with APIs using ReactJS. I know the basics of reactjs pretty well but I'm unable to read the response. I've a json response from youtube api.
Initially i got
TypeError: items.map is not a function.
But then i realized that i might be getting an Object and not an array. I solved the problem by items: json.statistics. But now I'm getting other error i.e
TypeError: items is undefined
I just want to fetch 3 information viz viewCount, subscriberCount and videoCount. I've written this code
import React, {Component} from 'react';
import './App.css';
class App extends Component {
constructor(props) {
super(props);
this.state = {
items: [],
isLoaded: false
}
}
componentDidMount() {
fetch('https://www.googleapis.com/youtube/v3/channels?part=statistics&id=UCOYqNBjmWF8j-PzI7ZPjt_w&key=AIzaSyAMeZQW6sUQgLdDTnMVeokfbcFcT2A9SuA')
.then(res => res.json())
.then(json => {
this.setState({
isLoaded: true,
items: json.statistics
})
});
}
render() {
var {isLoaded, items} = this.state;
if(!isLoaded) {
return (<div>Loading...</div>)
}
else {
return (
<div>
<ul>
{
items.map(item => (
<li key={item.id}>
Total views: {item.viewCount}
Total subscribers: {item.subscriberCount}
Total videos: {item.videoCount}
</li>
))}
</ul>
</div>
)
}
}
}
export default App;
It seems like the problem is in your setState(). Try something like this:
import React, { Component } from "react";
import "./styles.css";
class App extends Component {
constructor(props) {
super(props);
this.state = {
items: [],
isLoaded: false
};
}
componentDidMount() {
fetch(
"https://www.googleapis.com/youtube/v3/channels?part=statistics&id=UCOYqNBjmWF8j-PzI7ZPjt_w&key=AIzaSyAMeZQW6sUQgLdDTnMVeokfbcFcT2A9SuA"
)
.then(res => res.json())
.then(({ items }) => {
this.setState({
isLoaded: true,
items
});
});
}
render() {
var { isLoaded, items } = this.state;
if (!isLoaded) return <div>Loading...</div>;
return (
<div>
<ul>
{items.map(({ id, statistics }) => (
<li key={id}>
Total views: {statistics.viewCount}
Total subscribers: {statistics.subscriberCount}
Total videos: {statistics.videoCount}
</li>
))}
</ul>
</div>
);
}
}
Also, you don't need an if else statement if you have a return. Either use a ternary operator or just remove the else.
Here's the sandbox if you want to take a look at it. Let me know if it helps.
You are getting data in items array, you need to set json.items in state,
this.setState({
isLoaded: true,
items: json.items
})
And then you will get statistics object data,
{
items.map(item => (
<li key={item.id}>
Total views: {item.statistics.viewCount}
Total subscribers: {item.statistics.subscriberCount}
Total videos: {item.statistics.videoCount}
</li>
))
}
Demo

How to use React SetState on nested data with empty top level names?

I have the following JSON data:
[
{"ID":1,"Latitude":"-41.276253","Longitude":"173.283842","Image":"Church.jpg"},
{"ID":2,"Latitude":"-41.267783","Longitude":"173.279114","Image":"Centre.jpg"}
]
I am trying to import it so it can be rendered & started with the following code:
componentDidMount() {
fetch('/home/briefsJson').then(response => response.json()).then(data => {
console.log(data);
this.setState({
latitude: data.Latitude,
longitude: data.Longitude,
image: data.Image
});
});
}
This doesn't as the data is multidimensional/nested. But every example I've found is using better structured data with top level names.
How can I use setState & render to display this data?
If you want to import json from a js file you would do it like this.
Data.js
const Data = [
{"ID":1,"Latitude":"-41.276253","Longitude":"173.283842","Image":"Church.jpg"},
{"ID":2,"Latitude":"-41.267783","Longitude":"173.279114","Image":"Centre.jpg"}
]
export default Data
Then import it where you want to use it. Now you can map through the data as you like.
App.js
import Data from './data'
import React, {Component} from 'react'
class App extends Component {
state = { Data:[] }
componentDidMount() { this.setState({ Data: Data }) }
render() {
return(
<div> {this.state.Data.map(item => <div> The id is: {item.ID} </div> }</div>
)
}
}
Maybe you want to change the names of the items, and return a new data structure with less attributes this is how you would do it.
componentDidMount() {
fetch('/home/briefsJson').then(response => response.json()).then(data => {
const newData = data.map(item => {
latitude:item.Latitude,
longitude: item.Longitude,
image: item.Image}
}
this.setState({
Data:newData
});
});
}
Now if you want to display this data in render.
renderData = () => {
return (
<div>
{this.state.Data.map(item => (
<div>
{item.latitude}
{item.longitude}
<img src={item.img} />
</div>
)}
</div>
)
}
render() {
return (
<div> {this.renderData()} </div>
)
}
It would probably just be easier to first construct what you want, then do a mapping in the rendering. It looks like you don't even need to do anything to convert it, since the json data is exactly what you want in the first place. So:
componentDidMount() {
fetch('/home/briefsJson').then(response => response.json()).then(data => {
console.log(data);
this.setState({ data });
});
}
render() {
return (
<div>
{this.state.data.map(datum => (element))}
</div>
);
}

Can't access JSON object information React/Redux

Feels like I'm missing something obvious here - but I can't figure out how to access my JSON data. I have a Container component:
class About extends Component {
componentDidMount(){
const APP_URL = 'http://localhost/wordpress/'
const PAGES_URL = `${APP_URL}/wp-json/wp/v2/pages`
this.props.fetchAllPages(PAGES_URL, 'about')
}
render(){
return (
<div>
<Header/>
<div className="bg">
<div className="home-wrapper">
<h1>AAAAABBBBBOOOOUUUUUT</h1>
<Counter/>
<AboutInfo />
</div>
</div>
<Footer/>
</div>
)
}
}
const mapDispatchToProps = (dispatch) => {
return bindActionCreators({ fetchAllPages }, dispatch)
}
export default connect(null, mapDispatchToProps)(About);
And a Smart component:
class AboutInfo extends Component {
render(){
console.log(this.props.page);
console.log(this.props.page.id);
return (
<div>
<h1>This is ID: {this.props.page.id}</h1>
</div>
)
}
}
const mapStateToProps = ({ page }) => {
return { page }
}
export default connect(mapStateToProps)(AboutInfo);
My action:
export const fetchAllPages = (URL, SLUG) => {
var URLEN;
if(!SLUG){
URLEN = URL
} else {
URLEN = URL + "?slug=" + SLUG
}
return (dispatch) => {
dispatch(fetchRequest());
return fetchPosts(URLEN).then(([response, json]) => {
if(response.status === 200){
if(!SLUG) {
dispatch(fetchPagesSuccess(json))
} else {
dispatch(fetchPageBySlugSuccess(json))
}
} else {
dispatch(fetchError())
}
})
}
}
const fetchPageBySlugSuccess = (payload) => {
return {
type: types.FETCH_PAGE_BY_SLUG,
payload
}
}
My reducer:
const page = (state = {}, action) => {
switch (action.type) {
case FETCH_PAGE_BY_SLUG:
console.log(action.paylod)
return action.payload
default:
return state
}
}
This gives me:
When I console.log(this.props.page) in my AboutInfo component, it prints the object, but when I print console.log(this.props.page.id) it gives me undefined. Why can't I print the JSON content? Thanks!
page is an array and hence this.props.page.id is undefined. You might want to access the first element in array in which case you would do
this.props.page[0].id
but you might also need to add a test, since before the response is available you will be trying to access page[0].id and it might break.
You could instead write
this.props.page && this.props.page[0] && this.props.page[0].id
Getting data from the store is async So you must adding loading varibale on your reducer
class AboutInfo extends Component {
render(){
if(this.props.loading) return (<div>loading</div>);
return (
<div>
<h1>This is ID: {this.props.page.id}</h1>
</div>
);
}
}
const mapStateToProps = ({ page, loading }) => {
return { page, loading }
}
on your action try returing
json.page[0]
That is because page is an array and the id is a property of its 1st element.
So use this.props.page[0].id
If the logged object in your screenshot is the this.props.page then you will need and additional .page as that is also a part of the object this.props.page.page[0].id