React get inner JSON object from api - json

Update: How do I get an array (currentSchedule) within an array (response)?
I am trying to get the JSON object in "response" within the JSON code below. For instance, I want to get the title & description in "response", but it is not returning anything for me with the codes that I implemented below.
all.json
{"responseCode":200,
"responseMessage":"Channel Listing",
"response":[{
"id":395,
"title":"Title 1",
"description":"Description 1",
"currentSchedule":[{"eventId":"123456","title":"Hello Title"]}
}]
}
App.js
class App extends Component {
constructor(props){
super(props);
this.state = {
items: [],
isLoaded: false,
}
}
componentDidMount(){
fetch('/all.json')
.then(res => {
res.json()
})
.then(json => {
this.setState({
isLoaded: true,
items: [],
})
});
}
render() {
var { isLoaded, items } = this.state;
if(!isLoaded) {
return <div>Loading...</div>;
}
else {
return (
<div className="App">
<ul>
{items.map(item => (
<li key={item.id}>
Title: {item.title} | Description: {item.description}
</li>
))};
</ul>
</div>
);
}
}
}
export default App;

You need to assign response in your setState to view it, somthing like this
componentDidMount(){
fetch('/all.json')
.then(res => res.json())
.then(json => {
this.setState({
isLoaded: true,
items: json.response,
})
}).catch(console.log);
}

Related

Displaying data from json as suggestions under a searchbar in reactjs

I have a component called AutoFill which looks like this,
const AutoFill = (props) => {
console.log('proppppppsss', props)
const results = props.results || []
return (
<ul>
{results.map(({ name, href }) => (
<li key={href}>
<a href={href} target='_blank' rel='noopener noreferrer' key={href}>
{name}
</a>
</li>
))}
</ul>
)
}
The Json File where data gets passed through looks like this,
[
{
"a": {
"apple": {
"name": "apple",
"href": "https://www.apple.com/"
},
"armadillo": {
"name": "armadillo",
"href": "https://www.armadillo.com/"
}
},
"b": {
"box": {
"name": "box",
"href": "https://www.box.com/"
},
"berserk": {
"name": "berserk",
"href": "https://www.berserk.com/"
}
}
}
]
The fetch that gets the data from the json
import fetch from 'isomorphic-fetch'
const FetchAndParseResults = (url) => {
return fetch(url).then(response => {
const parsedJson = response.json()
return parsedJson
})
}
export default FetchAndParseResults
The search that makes use of the autofill
import AutoFill from './autofill'
import PropTypes from 'prop-types'
export default class Searchbar extends React.Component {
constructor (props) {
super(props)
this.state = {
className: Styles.input,
icon: Styles.icon__wrapper,
value: []
}
this.input = React.createRef()
}
openInput = () => {
this.setState({
className: Styles.input__active,
icon: Styles.iconWidth
}, () => {
this.input.focus()
})
this.props.onOpen && this.props.onOpen()
}
closeInput = () => {
this.setState({
className: Styles.input,
icon: Styles.icon__wrapper
})
this.props.onClose && this.props.onClose()
}
handleChange = event => {
let value = event.target.value
this.setState({ value })
this.props.performSearch(value)
}
handleSubmit = event => {
event.preventDefault()
}
render () {
console.log('results', this.props.results)
console.log('state.value', this.state.value)
return (
<div>
<form onSubmit={this.handleSubmit} className={Styles.search}>
<div className={this.state.icon}>
<Icon className={Styles.icon__wrapper} iconName='faSearch' onClick={this.openInput} />
</div>
<Search autoComplete='off' value={this.state.value} onChange={this.handleChange} id='search' tabIndex='0' myref={input => { this.input = input }} className={this.state.className} onBlur={this.closeInput} placeholder='Search' />
</form>
<div>
<AutoFill results={this.props.results} />
</div>
</div>
)
}
}
Search.propTypes = {
performSearch: PropTypes.func,
results: PropTypes.array
}
the searchContainer that makes use of everything
import React from 'react'
import Searchbar from './index.js'
import FetchAndParseResults from './FetchAndParseResults.js'
class SearchContainer extends React.Component {
state = {
results: []
}
performSearch = event => {
return FetchAndParseResults('static/autofill.json').then(data => {
this.setState({ results: data })
})
}
render () {
return (
<Searchbar
performSearch={this.performSearch}
results={this.state.results}
/>
)
}
}
export default SearchContainer
At <a href={href} target='_blank' rel='noopener noreferrer' key={href}>{name}</a>
the data of the names should be displayed but instead of the names i get this,
https://gyazo.com/647176b09afcd55b4238f7975c0e7488
An empty unordered list.
Therefore help would be highly appreciated,
and looked into.

.map() only displaying the last item from array

I want to use the Citybik.es API (http://api.citybik.es/) to show data on a Leaflet map.
At the moment, the code is only showing the last item from the bikeData.map(), inside the render function.
The console.log(data) is showing every iterated item from the bikeData.map(), but only displaying the last item.
I am looking for something like this.
What am I missing?
The response looks something like this:
{
"networks": [
{
"company": [
"Bike U Sp. z o.o."
],
"href": "/v2/networks/bbbike",
"id": "bbbike",
"location": {
"city": "Bielsko-Bia\u0142a",
"country": "PL",
"latitude": 49.8225,
"longitude": 19.044444
},
"name": "BBBike"
},
{
"company": [
"PBSC",
"Alta Bicycle Share, Inc"
],
"href": "/v2/networks/melbourne-bike-share",
"id": "melbourne-bike-share",
"location": {
"city": "Melbourne",
"country": "AU",
"latitude": -37.814107,
"longitude": 144.96328
},
"name": "Melbourne Bike Share"
}
}
Here's the JavaScript:
import React, { Component } from 'react';
import L from 'leaflet';
import { Map, TileLayer, Marker, Popup } from 'react-leaflet';
// code for map marker icon
var myIcon = L.icon({
iconUrl: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABkAAAApCAYAAADAk4LOAAAFgUlEQVR4Aa1XA5BjWRTN2oW17d3YaZtr2962HUzbDNpjszW24mRt28p47v7zq/bXZtrp/lWnXr337j3nPCe85NcypgSFdugCpW5YoDAMRaIMqRi6aKq5E3YqDQO3qAwjVWrD8Ncq/RBpykd8oZUb/kaJutow8r1aP9II0WmLKLIsJyv1w/kqw9Ch2MYdB++12Onxee/QMwvf4/Dk/Lfp/i4nxTXtOoQ4pW5Aj7wpici1A9erdAN2OH64x8OSP9j3Ft3b7aWkTg/Fm91siTra0f9on5sQr9INejH6CUUUpavjFNq1B+Oadhxmnfa8RfEmN8VNAsQhPqF55xHkMzz3jSmChWU6f7/XZKNH+9+hBLOHYozuKQPxyMPUKkrX/K0uWnfFaJGS1QPRtZsOPtr3NsW0uyh6NNCOkU3Yz+bXbT3I8G3xE5EXLXtCXbbqwCO9zPQYPRTZ5vIDXD7U+w7rFDEoUUf7ibHIR4y6bLVPXrz8JVZEql13trxwue/uDivd3fkWRbS6/IA2bID4uk0UpF1N8qLlbBlXs4Ee7HLTfV1j54APvODnSfOWBqtKVvjgLKzF5YdEk5ewRkGlK0i33Eofffc7HT56jD7/6U+qH3Cx7SBLNntH5YIPvODnyfIXZYRVDPqgHtLs5ABHD3YzLuespb7t79FY34DjMwrVrcTuwlT55YMPvOBnRrJ4VXTdNnYug5ucHLBjEpt30701A3Ts+HEa73u6dT3FNWwflY86eMHPk+Yu+i6pzUpRrW7SNDg5JHR4KapmM5Wv2E8Tfcb1HoqqHMHU+uWDD7zg54mz5/2BSnizi9T1Dg4QQXLToGNCkb6tb1NU+QAlGr1++eADrzhn/u8Q2YZhQVlZ5+CAOtqfbhmaUCS1ezNFVm2imDbPmPng5wmz+gwh+oHDce0eUtQ6OGDIyR0uUhUsoO3vfDmmgOezH0mZN59x7MBi++WDL1g/eEiU3avlidO671bkLfwbw5XV2P8Pzo0ydy4t2/0eu33xYSOMOD8hTf4CrBtGMSoXfPLchX+J0ruSePw3LZeK0juPJbYzrhkH0io7B3k164hiGvawhOKMLkrQLyVpZg8rHFW7E2uHOL888IBPlNZ1FPzstSJM694fWr6RwpvcJK60+0HCILTBzZLFNdtAzJaohze60T8qBzyh5ZuOg5e7uwQppofEmf2++DYvmySqGBuKaicF1blQjhuHdvCIMvp8whTTfZzI7RldpwtSzL+F1+wkdZ2TBOW2gIF88PBTzD/gpeREAMEbxnJcaJHNHrpzji0gQCS6hdkEeYt9DF/2qPcEC8RM28Hwmr3sdNyht00byAut2k3gufWNtgtOEOFGUwcXWNDbdNbpgBGxEvKkOQsxivJx33iow0Vw5S6SVTrpVq11ysA2Rp7gTfPfktc6zhtXBBC+adRLshf6sG2RfHPZ5EAc4sVZ83yCN00Fk/4kggu40ZTvIEm5g24qtU4KjBrx/BTTH8ifVASAG7gKrnWxJDcU7x8X6Ecczhm3o6YicvsLXWfh3Ch1W0k8x0nXF+0fFxgt4phz8QvypiwCCFKMqXCnqXExjq10beH+UUA7+nG6mdG/Pu0f3LgFcGrl2s0kNNjpmoJ9o4B29CMO8dMT4Q5ox8uitF6fqsrJOr8qnwNbRzv6hSnG5wP+64C7h9lp30hKNtKdWjtdkbuPA19nJ7Tz3zR/ibgARbhb4AlhavcBebmTHcFl2fvYEnW0ox9xMxKBS8btJ+KiEbq9zA4RthQXDhPa0T9TEe69gWupwc6uBUphquXgf+/FrIjweHQS4/pduMe5ERUMHUd9xv8ZR98CxkS4F2n3EUrUZ10EYNw7BWm9x1GiPssi3GgiGRDKWRYZfXlON+dfNbM+GgIwYdwAAAAASUVORK5CYII=',
iconSize: [25, 41],
iconAnchor: [12.5, 41],
popupAnchor: [0, -41]
});
class App extends Component {
state = {
location: {
lat: 51.505,
lng: -0.09,
},
bikeData: [],
zoom: 2,
}
//lifecycle method to get the bike information
componentDidMount() {
fetch('https://api.citybik.es/v2/networks')
.then(res => res.json())
.then(response => {
const networkData = response.networks;
networkData.map((data) => {
console.log(data)
this.setState({
bikeData: [data]
});
})
})
}
render() {
const position = [this.state.location.lat, this.state.location.lng]
const bikeData = this.state.bikeData;
return (
<Map className="map" center={position} zoom={this.state.zoom}>
<TileLayer
attribution="&copy <a href="http://osm.org/copyright">OpenStreetMap</a> contributors"
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
/>
{
bikeData && bikeData.map((data) => {
console.log(data)
return (
<Marker
icon={myIcon}
key={data.id}
position={[data.location.latitude, data.location.longitude]}>
<Popup>
Name: {data.name} <br />
Station Details: {[data.location.city, data.location.country]}
</Popup>
</Marker>
)
})
}
</Map>
)
}
}
ReactDOM.render(<App/>,
document.getElementById('root')
);
You're repeatedly overwriting the bikeData state item:
fetch('https://api.citybik.es/v2/networks')
.then(res => res.json())
.then(response => {
const networkData = response.networks;
networkData.map((data) => {
console.log(data)
this.setState({ // ***
bikeData: [data] // *** Here
}); // ***
})
})
It's not clear why you're using map there at all; certainly, map is the wrong tool if you're not going to return a value from the callback and not going to use the array map creates.
I can't say for sure, but it seems like you just want to use networkData directly:
fetch('https://api.citybik.es/v2/networks')
.then(res => res.json())
.then(response => {
const networkData = response.networks;
this.setState({bikeData: networkData});
})
Note that I'm assuming you want to overwrite bikeData with the result, not add to it.
Or if you want to transform that data in some way, you'd use the result of map:
fetch('https://api.citybik.es/v2/networks')
.then(res => res.json())
.then(response => {
const networkData = response.networks;
this.setState({
bikeData: networkData.map((data) => {
return /*...do something to data...*/;
})
});
})
(Same assumption.)
To add to bikeData, you'd need to use the callback form of setState:
this.setState(({bikeData}) => ({
bikeData: [...bikeData, ...networkData.map((data) => {
return /*...do something to data...*/;
})]
});
Also note that you have an error in your fetch call (you're not alone, a lot of people do this, so many I wrote it up on my anemic little blog): You haven't checked res.ok:
fetch('https://api.citybik.es/v2/networks')
.then(res => { // ***
if (!res.ok) { // ***
throw new Error(res.status); // ***
} // ***
}) // ***
.then(res => res.json())
.then(response => {
// ...
Try this:
componentDidMount() {
fetch('https://api.citybik.es/v2/networks')
.then(res => res.json())
.then(response => {
const networkData = response.networks; //which is currently an array
this.setState({
bikeData: networkData
});
})
}
You are not recommended to do setState inside loop. So do setState outside the loop. Also the way you push data into array isn't correct. Try below solution
const bikeDataArray = this.state.bikeData;
networkData.map(data => {
console.log(data)
bikeDataArray.push(data);
})
this.setState({
bikeData: bikeDataArray
});

How can i put the data array gained from the fetch return to the Dropdown component?

I'm trying to make a simple dropdown list which data is gained from a fetch return..
if I use console to view the return, it shows like this :
[
{
"ID": "BOGOR~10"
"Location": "BOGOR"
},
{
"ID": "JADETABEK~16"
"Location": "JADETABEK"
}
]
if I want to take the location BOGOR and JADETABEK and put them into a Dropdown, how can I do that? this is my testing class
import React , { Component } from 'react';
import { View , StyleSheet , Text , Dimensions } from 'react-native';
import { Dropdown } from 'react-native-material-dropdown';
const ScreenWidth = Dimensions.get('window').width;
const Screenheight = Dimensions.get('window').height;
export default class testing extends Component {
constructor(props) {
super(props)
this.state = {
data: []
}
}
componentDidMount() {
fetch(url , {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({"lokasi":
{
}
})
})
.then(response => response.json())
.then(res => {
this.setState({
data: res.PilihLokasiResult.Lokasi
})
alert(res.PilihLokasiResult.Lokasi)
})
}
render() {
return(
<View style={styles.container}>
<View>
<Text>{this.state.location}</Text>
<Dropdown label="select location" style={{width: 400 }}/>
</View>
</View>
)
}
}
You need to format the data since react-native-material-dropdown accepts data in the form of {value: 'Sample'}
this.state = {
data: [],
dropDownData: []
}
const formatData = (data) => {
return data.map(dataObj => {
return {value: dataObj.Location} // return based on location
})
}
.then(res => {
const dropDownData = formatData(res.PilihLokasiResult.Lokasi)
this.setState({
data: res.PilihLokasiResult.Lokasi,
dropDownData
})
})
<Dropdown label="select location" data={this.state.dropDownData} style={{width: 400 }}/>

Is it possible to have more than one parameters in data for a FlatList?

Like this for example:
<FlatList data={ this.state.foods, this.state.trees }
renderItem={({item}) => <View><Text>{item.food}</Text><Text>{item.tree}</Text></View>
/>
As long as I have the same key (id), is it possible this can work like this?
this.state.foods:
[{
"id": "1",
"food":"chicken",
"cal":"1000",
}]
this.state.trees:
[{
"id": "1",
"tree":"pine",
"size":"10",
}]
EDIT:
render(){
const {trees, foods} = this.state
const combinedArray = trees.map(tree => Object.assign(tree, foods.find(food => food.id == tree.id)));
return(
componentDidUpdate(prevProps, prevState) {
if (!prevState.foods) {
fetch('https://www.example.com/React/food.php')
.then((response) => response.json())
.then((responseJson) => {
this.setState({
isLoading: false,
foods: responseJson.map(item => ({ ...item, progress: new Animated.Value(0), unprogress: new Animated.Value(1) }))
}, function() {
});
})
.catch((error) => {
//console.error(error);
});
fetch('https://www.example.com/React/tree.php')
.then((response) => response.json())
.then((responseJson) => {
this.setState({
isLoading: false,
trees: responseJson
}, function() {
});
})
.catch((error) => {
//console.error(error);
});
}
}
You need to supply a single array to a Flatlist data.
You can group the objects based on id and use them
const {trees, foods} = this.state
const combinedArray = trees.map(tree => Object.assign(tree, foods.find(food => food.id == tree.id)));
and then use combinedArray in the Flatlist
If your state is undefined or null initially then you need to add
constructor(props) {
super(props)
this.state = {
trees: [],
foods: []
}
}
to your class component.

What is the best way to construct a dropdown and fetch JSON data dynamically from a URL

My dropdown has three Items ===> Item0,Item1,Item2 .
Every time I select a particular item, I would like to fetch the JSON data and display it on the page (on IOS). I do not understand where exactly to define the onPress event for the Dropdown.
Any help would be appreciated.
const leveldata = [
{ value: 'level1', props: { disabled: true } },
{ value: 'level2' },
{ value: 'level3' },
];class TopScores extends Component {
constructor(props) {
super(props);
this.onChangeText = this.onChangeText.bind(this);
this.state = {
data: [],
};
}
onChangeText() {
if (leveldata.value === 'leve1') {
fetch('url')
.then((response) => response.json())
.then((responseData) => {
this.setState({
newdata: responseData.newdata,
});
})
.done();
} else if (leveldata.value === 'level2') {
fetch('url1')
.then((response) => response.json())
.then((responseData) => {
this.setState({
newdata: responseData.newdata,
});
})
.done();
}
}
render() {
console.log('data:', this.state.data);
return (
<View>
<View style={styles.container1}>
<Image
/* eslint-disable global-require */
source={require('../Images/Top.png')}
/* eslint-enable global-require */
/>
<Text style={styles.Text1}> Top Contenders</Text>
</View>
<View>
<Dropdown
data={leveldata}
label='Level'
onChangeText={this.onChangeText}
/>
</View>
</View>
);
}
}
If I remember correctly you need to add the onChangeText prop.
import React, { Component } from 'react';
import {
Text,
View,
StyleSheet,
Image
} from 'react-native';
import { Dropdown } from 'react-native-material-dropdown';
const leveldata = [
{ value: 'level1', props: { disabled: true } },
{ value: 'level2' },
{ value: 'level3' }
];
class TopScores extends Component {
constructor(props) {
super(props);
this.onChangeText = this.onChangeText.bind(this);
this.state = {
data: []
};
}
onChangeText(text) {
if(text === 'leve1'){
fetch('url')
.then((response) => response.json())
.then((responseData) => {
this.setState({
newdata: responseData.newdata,
});
})
.done();
}
}
render() {
return (
<View>
<Dropdown
data={leveldata}
label='Level'
onChangeText={this.onChangeText} />
</View>
);
}
}