How to get all JSON data inside the brackets using fetch? - javascript

I am newbie to react native and I would like to create a simple app to fetch JSON data.
Here is my json file.
[
{
"fruit": "Apple",
"size": "Large",
"color": "Red"
},
{
"fruit": "Orange",
"size": "big",
"color": "Orange"
}
]
Here is my react native code
export default class App extends React.Component {
constructor(props) {
super(props);
this.state = { data: '' };
}
componentDidMount = () => {
fetch('https://othersite.my.json', {
method: 'GET'
})
.then((response) => response.json())
.then((responseJson) => {
console.log(responseJson);
this.setState({
data: responseJson
})
})
.catch((error) => {
console.error(error);
});
}
render() {
return (
<View style={styles.container}>
<Text>
{this.state.data}
//for debug {this.state.data.fruit}
</Text>
</View>
);
}
}
But it doesn't work.

Your fetch looks good in there. Considering you are able to fetch data from the API and set the state. You can use map() function to display your data
render(){
return (
<View style={styles.container}>
{this.state.data.map((item) => {
console.log(item.fruit)
console.log(item.size)
console.log(item.color)
})
</View>
);
}

If the json file is inside your react project, you can import the like this:
const fruits = require('path/to/json/my.json');
console.log(fruits[0].size);

Related

React Native Spotify api getting a users playlist

Hi I'm currently working on a react native app and I'm trying to get a users playlist and then return it in a flatlist. I've completed getting a users access_token but I'm a little stuck on figuring out how to actually use the data. I'm fairly new to using api data.
export default function SpotifyGetPlaylist(props) {
const { colors } = useTheme();
const [token, setToken] = useState('');
const [data, setData] = useState({});
React.useEffect(() => {
getData();
}, []);
const getData = async() => {
setToken (await AsyncStorage.getItem('#access_token'));
console.log("token retrieved")
}
const handleGetPlaylists = () => {
axios.get("https://api.spotify.com/v1/me/playlists", {
headers: {
Authorization: `Bearer ${token}`,
},
}).then(response => {
setData(response.data);
console.log(response.data)
})
.catch((error) => {
console.log(error);
});
};
}
This part works fine and returns data into the console as such
Object {
"collaborative": false,
"description" : "Maailman – Päivittäinen katsaus siihen, mitä kappaleita kuunnellaan eniten juuri nyt.",
"external_urls": Object {
"spotify": "https://open.spotify.com/playlist/37i9dQZEVXbMDoHDwVN2tF",
},
"href" : "https://api.spotify.com/v1/playlists/37i9dQZEVXbMDoHDwVN2tF",
"id" : "37i9dQZEVXbMDoHDwVN2tF",
"images": Array [
Object {
"height": null,
"url" : "https://charts-images.scdn.co/assets/locale_en/regional/daily/region_global_large.jpg",
"width" : null,
},
],
"name": "Maailman – Top 50",
"owner": Object {
"display_name" : "Spotify",
"external_urls": Object {
"spotify": "https://open.spotify.com/user/spotify",
},
"href": "https://api.spotify.com/v1/users/spotify",
"id" : "spotify",
"type": "user",
"uri" : "spotify:user:spotify",
},
"primary_color": null,
"public" : true,
"snapshot_id" : "NzAzNDIxMzk0LDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDY2Njk=",
"tracks": Object {
"href" : "https://api.spotify.com/v1/playlists/37i9dQZEVXbMDoHDwVN2tF/tracks",
"total": 50,
},
"type": "playlist",
"uri" : "spotify:playlist:37i9dQZEVXbMDoHDwVN2tF",
},
But I'm having problems actually rendering anything into the Flatlist which at the moment looks like this.
const renderItem = ({item}) => {
<Item title={item.name}/>
}
return (
<View style={styles.container}>
<Button
onPress = {handleGetPlaylists}
color = "#1DB954"
style = {{ color: colors.text, width: 100 }}
title = "Get your playlists"/>
<FlatList
data = {data}
renderItem = {renderItem}
keyExtractor= {(item) => item.id.toString()}
/>
</View>
)
I'm unsure how I get the data from the api my hunch is that I would have to use data.items.name to access it but it doesnt work for me. Help is much appreciated
Nothing is appearing in the FlatList render because you're not returning your Item. Because you have curly braces around the body of the function, you have to explicitly return the component.
const renderItem = ({item}) => {
return <Item title={item.name} />;
}

I can't render my data from the DB with a .map

I'm currently working on a react native app, and I have an issue about render information (in an array) that I fetch from my DB. To do that I have to write a .map.
I receive the data from the fetch in the console.log.
When I call my function with this "()".
<Text>Choisissez votre Choix Club </Text>
<TouchableOpacity>
<View>
<Text>{this.renderMesClubs()}</Text>
</View>
</TouchableOpacity>
An error message appear
TypeError: undefined is not an object (evaluating '_this.state.sport.club.map')
Below you can find the all code page.
class ChoixClub extends Component {
constructor(props) {
super(props);
this.state = {
sport: {club: []},
};
}
getMesClubs = () => {
const headers = new Headers({'Content-type': 'application/json'});
const options = {
method: 'GET',
headers: headers,
};
fetch('http://localhost:8080/inscription/sport', options)
.then((response) => {
return response.json();
})
.then(
(data) => {
const club = JSON.stringify(data);
this.setState({sport: club});
console.log(this.state.sport.club);
},
(err) => {
console.log(err);
},
);
};
renderMesClubs = () => {
return this.state.sport.club.map((element) => {
return (
(
<View className="articles">
<Text>{element.nomClub}</Text>
</View>
),
console.log(element.nomClub)
);
});
};
componentDidMount() {
this.getMesClubs();
}
render() {
return (
<SafeAreaView>
<Text>Choisissez votre Choix Club </Text>
<TouchableOpacity>
<View>
<Text>{this.renderMesClubs()}</Text>
</View>
</TouchableOpacity>
<Text>Choisissez votre rival</Text>
<TouchableOpacity></TouchableOpacity>
</SafeAreaView>
);
}
}
export default ChoixClub;
I hope my message is clear enough for you to solve it, and thanks in advance for your answer!
You are calling JSON.stringify(data), which turns "data" into a string. assuming that the server is returning valid JSON, then calling response.json(), which you are already doing, should give you a Javascript object, hopefully an array, you should map over that, not turn it back into a string and map over the string.
to check if data really is an array you can use:
if(!Array.isArray(data)){
throw new Error('expected the response to be an array');
}
All your data is actually contained by an array, so you need to specify the element or iterate it. As #user1852503 said, no JSON.stringify is needed because .then((response) => { return response.json(); }) does the trick
// Let's your data
let data = [ { "_id": "5f44dcc0a3da3a3008a71e5d", "sport": { "_id": "5f44dcc0a3da3a3008a71e5e", "club": [ { "_id": "5f44dcc0a3da3a3008a71e5f", "nomClub": "String", "classement": "String", "dateMatch": "String", "classementDB": "String" } ] }, "__v": 0 } ];
data[0].sport.club.map(element => {
// I just console log it to see if it works
console.log(element.nomClub)
})

React Native Networking with react-native-router-flux

Hey guys I have a short question. I want to give every Button a other Page.
import React, { Component } from 'react';
import { ActivityIndicator, FlatList, Text, View, TouchableOpacity } from 'react-native';
export default class App extends Component {
constructor(props) {
super(props);
this.state = {
data: [],
isLoading: true
};
}
componentDidMount() {
fetch('https://reactnative.dev/movies.json')
.then((response) => response.json())
.then((json) => {
this.setState({ data: json.movies });
})
.catch((error) => console.error(error))
.finally(() => {
this.setState({ isLoading: false });
});
}
render() {
const { data, isLoading } = this.state;
return (
<View style={{ flex: 1, padding: 24 }}>
{isLoading ? <ActivityIndicator/> : (
<FlatList
data={data}
keyExtractor={({ id }, index) => id}
renderItem={({ item }) => (
<TouchableOpacity>
<Text>{item.title}</Text>
</TouchableOpacity>
)}
/>
)}
</View>
);
}
};
The Code give me the movie names as Button and I can click on everyone. Right now I want to open for every Button a other page with react-native-router-flux.
{
"title": "The Basics - Networking",
"description": "Your app fetched this from a remote endpoint!",
"movies": [
{
"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"
}
]
}
This is the Json Data where I fetch the names. Maybe the "id" will help me, but I really dont know what can I right now do.
I can only give you some recommend, because it is too rough to explain although is is a short question.
I remember using react-native-router-flux have to import your scene(page) and using Actions.somepage() to route to the page. But using FlastList is hard to Actions.eachpage like this. (Maybe just my skills are not good enough to achieve)
If you want to achieve like your description, I will recommend you to create a new page component to handle all of the scene now we just called "HandlePage", and then you could add it to your TouchableOpacity by using like
import HandlePage from "./HandlePage";
...
<TouchableOpacity onPress={() => { Actions.HandlePage({page: item.id}); }}
So that you could control the page at HandlePage , take this parameter(id) to handle which page you want to render. Actually, is only using one Actions.HandlePage to route but have more flexible to render what you want.
Hope it could help.
Update:
Something like:
import StarWars from "./StarWars";
import TheMatrix from "./TheMatrix";
import Inception from "./Inception";
import Interstellar from "./Interstellar";
export default class HandlePage extends React.Component {
checkSwitch = param => {
switch (param) {
case "1":
return <StarWars/> ;
case "2":
return <TheMatrix recordCount = {this.state.recordCount}/>;
case "3":
return <Inception disabled = {this.state.disabled3}/>;
case "4":
return <Interstellar alert = {this.state.alert4}/>;
default:
return null;
}
};
render() {
return ({
this.checkSwitch(this.props.page)
})
}
}

React Native - Passing fetch data to Modal and using StackNavigator with Modal

In here I have two problems. First is I'm trying to fetch dome data from my api and then pass this data to modal upon tapping a button. I have tried to use "state" and then declare that state like;
constructor(props){
super(props)
this.state = {
tbl: [],
tbl_no: null,
}
}
fetchTblOccpd = async () => {
const response = await fetch('http://192.168.***.***:****/PndngVRoutes/Occupied/');
const json = await response.json();
this.setState({ tbl: json })
this.setState({ tbl_no: json })
}
render() {
return (
.....
<PndModal
modalVisible = { this.state.modalVisible }
setModalVisible = { (vis) => { this.setState({ modalVisible: vis }) }}
tbl_no = { this.state.tbl_no }
/>
)
}
But this didn't work. I'm targeting to fetch a data and pass it to my Modal.
Sample
My Second question is after passing some data to Modal, I'm targeting to navigate to another screen/view from my modal.
here's my code
export default class PndModal extends Component {
constructor(props) {
super(props);
this.state = {
pnd_Data: [],
modalVisible: props.modalVisible,
};
}
componentWillReceiveProps(nextProps) {
this.setState({
modalVisible: nextProps.modalVisible,
tbl_no: nextProps.tbl_no, //This is the data I'm trying to pass.
})
}
fetchOrdered = async () => {
const response = await fetch("http://192.168.254.***:****/PndngVRoutes/PendingView/" + this.state.tbl_no);
const json = await response.json();
this.setState({ pnd_Data: json })
}
componentDidMount() {
this.fetchOrdered();
}
_onPressItem = () => {
this.setState({
modalVisible: false,
});
}
render() {
return (
<Modal>
<View>
<View>
<View>
<Text>Table No: { this.state.tbl_no }</Text>
<FlatList
data = {this.state.pnd_Data}
numColumns = { 2 }
keyExtractor={(item, index) => index.toString()}
renderItem = {({ item }) =>
<View>
<Text>{ item.menu_name }</Text>
</View>
}
/>
<TouchableOpacity
onPress = { () => this.props.navigation.navigate('pend') }> // This is my navigation code
<Text>Add Order</Text>
</TouchableOpacity>
</View>
</View>
</View>
</Modal>
)
}
}
Hello Am not too use to react native but i think is must be the same as react , for the solution to your problem , i think you should use reusable component . then create then pass your data as a props.
Here is an example in react.
//My reusable component
const Modal=(props) =>{
return (
<div>
{props.data}
</div>
);
}
}
Then you call your reusable component then pass the results from the api to it.
<Modal
data ={this.state.pnd_Data}
/>
for the second question you can just add link that will navigate you .... there will be no problem for that .
you can read about reusable component here
https://itnext.io/react-component-class-vs-stateless-component-e3797c7d23ab

Getting error Invariant Violation tried to get frame out of range index?

I have create VenueList component. I want to display list using FlatList component in react native app. I am getting error: Invariant Violation tried to get frame out of range index (See screenshot).
Code:
VenueList.js:
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { View, Text, FlatList, StyleSheet } from 'react-native';
import { connect } from 'react-redux';
import { fetchVenues } from '../actions/venueAction';
class VenueList extends Component {
componentWillMount () {
this.props.fetchVenues();
}
renderItem = ({ item }) => (
<View style={styles.item}>
<Text>{item.attributes.name}</Text>
</View>
);
render() {
return (
<FlatList
styles={styles.container}
data={this.props.venues}
renderItem={this.renderItem}
/>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1
},
item: {
padding: 16,
borderBottomWidth: 1,
borderBottomColor: '#ccc'
}
});
VenueList.propTypes = {
fetchVenues: PropTypes.func.isRequired,
venues: PropTypes.array.isRequired
}
const mapStateToProps = state => ({
venues: state.venues.items
})
export default connect (mapStateToProps, { fetchVenues })(VenueList);
venueReducer.js:
import { FETCH_VENUES } from '../actions/types';
const initialState = {
items: []
}
export default function (state = initialState, action) {
switch (action.type) {
case FETCH_VENUES:
return {
...state,
items: action.payload
};
default:
return state;
}
}
venueAction.js:
import { FETCH_VENUES } from './types';
import axios from 'axios';
export const fetchVenues = () => dispatch => {
axios.get(`my_api_link`)
.then( venues =>
dispatch({
type: FETCH_VENUES,
payload: venues
})
)
.catch( error => {
console.log(error);
});
};
The data which I want to display from API endpoint has json data as follows:
{
"data": [
{
"type": "venues",
"id": "nb",
"attributes": {
"name": "Barasti Beach",
"description": "Barasti Beach is lotacated in the awesome barasti beach",
"price_range": "$$$",
"opening_hours": "10:30-12:40/16:00-2:00",
"organization": {
"id": "GD",
"legal_name": "Barasti",
"brand": "Barasti"
},
"place": {
"address": "Le Meridien Mina Seyahi Beach Resort & Marina, Dubai Marina - Dubai - United Arab Emirates",
"latitude": "25.092648",
"location": [
"Marina Bay",
"Dubai",
"Arab Emirate United"
]
}
}
}
],
"meta": {
"total": 1,
"cursor": {
"current": 1,
"prev": null,
"next": null,
"count": 25
}
}
}
See screenshot:
As per the the above response for the api request,
The problem is with the payload which is set in the actions. You need to pass the data from the api to the Flatlist since it accepts only arrays.
axios.get(`my_api_link`)
.then( venues =>
dispatch({
type: FETCH_VENUES,
payload: venues.data
})
)
EDIT:
Adding in VenueList.js component (if the api is returning values inside data key):
renderItem = ({ item }) => (
<View style={styles.item}>
<Text>{item.attributes.name}</Text>
</View>
);
render() {
return (
<FlatList
styles={styles.container}
data={this.props.venues.data}
renderItem={this.renderItem}
/>
);
}

Categories

Resources