I am trying to show menu where it can have parent child relationship, with flat structure it is working fine but with nested objects not able to do it.
The below is the JSON and reactJS code.
JSON -
{
"data": [
{
"to": "#a-link",
"icon": "spinner",
"label": "User Maintenance"
},
{
"content": [
{
"to": "#b1-link",
"icon": "apple",
"label": "System Controls"
},
{
"to": "#b2-link",
"icon": "user",
"label": "User Maintenance"
}
],
"icon": "gear",
"label": "System Preferences"
},
{
"to": "#c-link",
"icon": "gear",
"label": "Configuration"
}
]
}
ReactJS code -
export default class MenuComponent extends Component {
constructor() {
super();
this.state = {}
}
componentDidMount(){
fetch('http://localhost:8084/Accounting/rest/v1/company/menu?request=abc')
.then(response => response.json())
.then(parsedJSON => parsedJSON.data.map(menu => (
{
to: `${menu.to}`,
icon: `${menu.icon}`,
label: `${menu.label}`
// content: `${menu.content}`
}
)))
.then(content => this.setState({
content
}))
}
render() {
console.log('333');
console.log(this.state.content);
return (
<MetisMenu content={this.state.content} activeLinkFromLocation />
)
}
}
In JSON you can see the 'System Preference' has nested content.
Try this code
class MenuComponent extends Component {
constructor() {
super();
this.state = {
content : []
}
}
componentDidMount(){
fetch('http://localhost:8084/Accounting/rest/v1/company/menu?request=abc')
.then(response => response.json())
.then(parsedJSON => parsedJSON.data.map(menu => (
{
to: `${menu.to}`,
icon: `${menu.icon}`,
label: `${menu.label}`
// content: `${menu.content}`
}
)))
.then(content => this.setState({
content
}))
}
render() {
const {content} = this.state
if(content === undefined){
return <div>Content not found</div>;
}
if(content.length === 0){
return <div>Loading</div>;
}
return (
<MetisMenu content={content} activeLinkFromLocation />
)
}
}
export default MenuComponent
Related
I'm struggling to take certain value out of an API. I have no trouble mapping over the parts that I can immediately access using items.value, but when I can't get some of the more nested info. I'm specifically trying to access the value of "quantity" inside of pricing.
Here's my code
import "./StoreDisplay.css"
class StoreDisplay extends Component {
constructor(props) {
super(props)
this.state = {
error: undefined,
isLoaded: false,
items: []
}
}
componentDidMount() {
this.getData();
}
getData() {
fetch(url)
.then((res) => res.json())
.then(
(result) => {
this.setState({
isLoaded: true,
items: result,
});
console.log(result)
},
(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 (
<div id = "storeDisplay">
<ul className = "container">
{items.map(item => (
<li key = {item.title}>
<div className = "bundleName"> {item.title} {item.pricing.quantity}</div><img src = {item.asset} className = "img"></img>
</li>
))}
</ul>
</div>
);
}
}
}
Sample part of JSON from API:
[
{
"title": "100-Pack Bundle",
"desc": "",
"tag": "",
"purchaseLimit": 1,
"isAvailable": true,
"expireTimestamp": 1662538288,
"shopType": "specials",
"originalPrice": 10500,
"pricing": [
{
"ref": "Apex Coins",
"quantity": 6700
}
],
"content": [
{
"ref": "weapon_charm_charm_apex_asset_v22_misc_pathfinderemoji01",
"name": "MRVN Monitor",
"quantity": 1
},
{
"ref": "pack_cosmetic_rare",
"name": "Apex Pack",
"quantity": 100
}
],
"offerID": "220823_100-pack_bundle",
"asset": "https:\/\/shop-cdn.mozambiquehe.re\/dl_store_s14_0_bund_epic_100pack_a189.png"
},
It looks like item.pricing is actually an array of objects. From here you have a couple of choices, depending on what you want to do.
item.pricing will only ever have one element.
In this case, you can just take the first element:
<div className = "bundleName"> {item.title} {item.pricing[0].quantity}</div>
You want to list all the quantities
<div className = "bundleName"> {item.title} {item.pricing.map(pricing => pricing.quantity).join(" ")}</div>
or
<div className = "bundleName"> {item.title} {item.pricing.map(pricing => pricing.quantity).join(", ")}</div>
You want to have the sum of all quantities
<div className = "bundleName"> {item.title} {item.pricing.map(pricing => pricing.quantity).reduce((a, b) => a + b, 0)}</div>
I added my coding's for how to create state like at the end of this question above coding's are i will try but am not able to create like that state.
This is my json format coding to get through
"Results": {
"Piechart":[{
"labels": ["Under 18", "Age 18-54", "Age 55+"],
"datasets": [{
"data": [2000, 4000, 2850],
"backgroundColor": ["red", "blue", "green"]
}]
}]
}
Here is my React Code
this.state = {labels: [], datasets: []};
componentDidMount() {
this.pieChart().then(result => {
this.setState({diagramData: result.pieDiagramLabel});
}).catch(err => console.error(err));
}
async pieChart() {
let pieChart = await import('../data/result_log.json');
console.log(pieChart[0].Results.Piechart);
return {
pieDiagramLabel: pieChart[0].Results.Piechart.labels
}
}
How to get both label and datasets? And how to set into state like below format
this.state= {
"labels": ["Under 18", "Age 18-54", "Age 55+"],
"datasets": [{
"data": [2000, 4000, 2850],
}]
}
You can try like this
data.json
{
"Piechart": [
{
"labels": ["Under 18", "Age 18-54", "Age 55+"],
"datasets": [
{
"data": [2000, 4000, 2850],
"backgroundColor": ["red", "blue", "green"]
}
]
}
]
}
App.js
import React from "react";
import Results from "./data.json";
export default class App extends React.Component {
state = {
labels: [],
datasets: []
};
componentDidMount() {
this.setState({
labels: Results.Piechart[0].labels,
datasets: Results.Piechart[0].datasets
});
}
render() {
const { labels, datasets } = this.state;
return (
<div className="App">
{labels.map((label, index) => (
<p key={index}>{label}</p>
))}
<hr />
{datasets.map((data, index) => (
<p key={index}>{data.backgroundColor}</p>
))}
</div>
);
}
}
Live working demo https://codesandbox.io/s/fetch-local-json-6bq4m
Working on an app using the google maps API for geolocation with Reactjs. My aim right now is to simply render the entire JSON data to the window (will be used later). No errors, but nothing is rendering to the page. Am I trying to access the data inccorrectly?
class App extends Component {
constructor () {
super();
this.state = {
isLoaded: false,
results: {}
};
}
componentDidMount() {
fetch(geo_url)
.then(res => res.json())
.then(
(result) => {
this.setState({
isLoaded: true,
results: result.results
});
},
(error) => {
this.setState({
isLoaded: true,
error
});
}
)
}
render() {
const {error, isLoaded, results} = this.state;
if (error) {
return <div>Error: {error.message} </div>;
} else if (!isLoaded) {
return <div>Loading...</div>;
} else {
return (
<div className="App">
Location Data:
{results.geometry}
</div>
);
}
}
}
Below is a sample of the JSON i'm trying to access:
{
"results": [
{
"address_components": [
{
"long_name": "1600",
"short_name": "1600",
"types": [
"street_number"
]
},
{
"long_name": "Amphitheatre Parkway",
"short_name": "Amphitheatre Pkwy",
"types": [
"route"
]
},
{
"long_name": "Mountain View",
"short_name": "Mountain View",
"types": [
"locality",
"political"
]
},
{
"long_name": "Santa Clara County",
"short_name": "Santa Clara County",
"types": [
"administrative_area_level_2",
"political"
]
},
{
"long_name": "California",
"short_name": "CA",
"types": [
"administrative_area_level_1",
"political"
]
},
{
"long_name": "United States",
"short_name": "US",
"types": [
"country",
"political"
]
},
{
"long_name": "94043",
"short_name": "94043",
"types": [
"postal_code"
]
}
],
"formatted_address": "1600 Amphitheatre Pkwy, Mountain View, CA 94043, USA",
"geometry": {
"location": {
"lat": 37.422617,
"lng": -122.0853839
},
"location_type": "ROOFTOP",
"viewport": {
"northeast": {
"lat": 37.4239659802915,
"lng": -122.0840349197085
},
"southwest": {
"lat": 37.4212680197085,
"lng": -122.0867328802915
}
}
},
"place_id": "ChIJ2eUgeAK6j4ARbn5u_wAGqWA",
"plus_code": {
"compound_code": "CWF7+2R Mountain View, California, United States",
"global_code": "849VCWF7+2R"
},
"types": [
"street_address"
]
}
],
"status": "OK"
}
First render occurs before results are retrieved. Check in render() whether results exist already. If not, display a 'loading' message.
In addition to that, fix your handling of error while trying to retrieve data. You are setting a state.error variable which was not defined. Then, in render, display an error message if loading is done but there is an error.
First, you have to do :
<div className="App">
{this.state.results.geometry}
</div>
or
render() {
const {results} = this.state
return (
<div className="App">
{results.geometry}
</div>
);
}
}
But Like #Yossi saids, you result are not defined in you first render. That's why you have : "results not defined". You can use "lodash" to force your render. It's works even if I don't know if it's a good practice
You can test :
import _ from 'lodash';
render() {
const {results} = this.state
return (
{!_.isEmpty(results) &&
<div className="App">
{results.geometry}
</div>
}
);
}
It should be works :)
PS : sorry for my bad english ;)
You can set in state a key for error: false.
In componentDidMount its better to use then and catch for errors
componentDidMount() {
fetch(geo_url)
.then(res => res.json())
.then(
(result) => {
this.setState({
isLoaded: true,
results: result.results
});
},
(error) => {
this.setState({
isLoaded: true,
error
});
}
).catch(error) {
this.setState({
isLoaded: true,
error
})
}
}
I want to list the data from the service I use as it is in the example. Can you help me?
My code:
import React, { Component } from "react";
export default class CustomersTab extends Component {
constructor(props) {
super(props);
this.state = {
token: "",
isLoading: true,
dataSource: null
};
}
componentWillMount() {
tokenner()
.then(responseJson => {
const token = "Bearer " + responseJson.result.token;
this.setState({ token });
fetch(
"apiurl",
{
method: "GET",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
Authorization: token
}
}
)
.then(response => response.json())
.then(responseData => {
this.setState({
isLoading: false,
dataSource: responseData.result
});
});
})
.catch(error => console.warn(error));
}};
render() {
return (
<View>
<Text>
I WANT LİST DATA HERE
</Text>
</View> )}}
I tried to do it myself, but I could not build the loop structure. Only one data is displayed every time. What should I do?
you have to do something like this. Change id to what you want to display.
return (
<View>
<ListView
dataSource={this.state.dataSource}
renderRow={data => <Text>{data.id}</Text>}
/>
</View>
);
Please Import the View and Text from react native.
import {
Text,
View,
} from 'react-native';
constructor(props: Object) {
super(props);
this.state = {
dataSource: []
}
};
/* dataSource = [
{ "id": "1", "title": "Star Wars", "releaseYear": "1977" },
{ "id": "2", "title": "Back to the Future", "releaseYear": "1985" },
{ "id": "3", "title": "The Matrix", "releaseYear": "1999" },
{ "id": "4", "title": "Inception", "releaseYear": "2010" },
{ "id": "5", "title": "Interstellar", "releaseYear": "2014" }
]
*/
renderMovieList(){
return this.state.dataSource.map((movie, index) =>
<View
key={movie.id}
style={{ height:50 padding:10}}>
<Text> movie.title</Text>
<Text> movie.releaseYear</Text>
</View>
)
}
render() {
return (
<View style={{flex: 1, justifyContent:'center'}}>
{this.state.dataSource.length ? this.renderMovieList(): null}
</View>
);
}
This problem is giving me a huge headache so any help is welcome :)
In this component, I'm making 2 axios calls to different APIs: one for freegeoip and one for openweathermap. I'm storing the data in the currentCity state, which is an object with 2 keys, location and weather. The idea is that the app detects your current location (using freegeoip) and renders location name and weather data (using openweathermap).
I'm positive it's storing the state properly as console logs have confirmed. I can render the location data for currentCity state, but can't seem to render the weather data for currentCity state.
renderCurrentCity(city) {
console.log('state3:', this.state.currentCity);
console.log([city.weather.main]);
return(
<div>
<li>{city.location.city}, {city.location.country_name}</li> // Working
<li>{city.weather.main.temp}</li> // Not working
</div>
)
}
The console error I get:
Uncaught (in promise) TypeError: Cannot read property '_currentElement' of null
currentCity.location JSON:
{
"ip": // hidden,
"country_code": "FR",
"country_name": "France",
"region_code": "GES",
"region_name": "Grand-Est",
"city": "Reims",
"zip_code": "",
"time_zone": "Europe/Paris",
"latitude": 49.25,
"longitude": 4.0333,
"metro_code": 0
}
currentCity.weather JSON:
{
"coord": {
"lon": 4.03,
"lat": 49.25
},
"weather": [
{
"id": 800,
"main": "Clear",
"description": "clear sky",
"icon": "01d"
}
],
"base": "stations",
"main": {
"temp": 283.15,
"pressure": 1011,
"humidity": 43,
"temp_min": 283.15,
"temp_max": 283.15
},
"visibility": 10000,
"wind": {
"speed": 3.1,
"deg": 350
},
"clouds": {
"all": 0
},
"dt": 1493127000,
"sys": {
"type": 1,
"id": 5604,
"message": 0.1534,
"country": "FR",
"sunrise": 1493094714,
"sunset": 1493146351
},
"id": 2984114,
"name": "Reims",
"cod": 200
}
Rest of code:
import React, { Component } from 'react';
import axios from 'axios';
import WeatherList from './weatherlist';
import SearchBar from './searchbar';
const API_KEY = '95108d63b7f0cf597d80c6d17c8010e0';
const ROOT_URL = 'http://api.openweathermap.org/data/2.5/weather?'
export default class App extends Component {
constructor(props) {
super(props);
this.state = {
cities: [],
errors: '',
currentCity: {
location: {},
weather: {}
}
};
this.currentCity();
this.renderCurrentCity = this.renderCurrentCity.bind(this);
}
citySearch(city) {
const url = `${ROOT_URL}&appid=${API_KEY}&q=${city}`;
axios.get(url)
.then(response => {
const citiesArr = this.state.cities.slice();
this.setState({
cities: [response.data, ...citiesArr],
errors: null
});
})
.catch(error => {
this.setState({
errors: 'City not found'
})
})
}
currentCity() {
var city;
var country;
axios.get('http://freegeoip.net/json/')
.then(response => {
const lat = response.data.latitude;
const lon = response.data.longitude;
city = response.data.city;
country = response.data.country_name;
const url = `${ROOT_URL}&appid=${API_KEY}&lat=${lat}&lon=${lon}`;
const state = this.state.currentCity;
console.log('state1:',state);
this.setState({
currentCity: { ...state, location: response.data }
});
console.log(url);
axios.get(url)
.then(city => {
const state = this.state.currentCity;
console.log('state2:', state);
this.setState({
currentCity: { ...state, weather: city.data }
});
})
})
}
renderCurrentCity(city) {
console.log('state3:', this.state.currentCity);
console.log([city.weather.main]);
return(
<div>
<li>{city.location.city}, {city.location.country_name}</li>
<li>{city.weather.main.temp}</li>
</div>
)
}
render() {
return (
<div className={this.state.cities == false ? 'search': 'search-up'}>
<h1>What's the weather today?</h1>
<ul className='list-unstyled text-center'>
{this.renderCurrentCity(this.state.currentCity)}
</ul>
<SearchBar
onSearchSubmit={this.citySearch.bind(this)}
errors={this.state.errors} />
{this.state.cities == false ? null : <WeatherList cities={this.state.cities} />}
</div>
)
}
}
You are spreading your whole state when your receive the weather data:
this.setState({
currentCity: { ...state, weather: city.data }
});
it should be:
this.setState({
currentCity: { ...state.currentCity, weather: city.data }
});