fetching of json from url is stuck - json

Trying to fetch some json from the following url: https://talaikis.com/api/quotes/random/
I'm using an activity indicator while waiting for the json to be fetched. That apparently never happens and so the app just displays the activity indicator. I tried using the sample that is provided in the networking tutorial in the official react native documentation
Here is the code:
import React, { Component } from 'react';
import {AppRegistry, StyleSheet, Text, View, ActivityIndicator} from 'react-native';
import Header from '../header/Header';
export default class SingleQuote extends Component {
constructor(props) {
super(props);
this.state = {
isLoading: true
}
}
loadingQuoteFromUrl(){
return fetch('https://talaikis.com/api/quotes/random/')
.then((response) => response.json())
.then((responseJson) => {
this.setState({
isLoading: false,
dataSource: responseJson,
}, function(){
});
})
.catch((error) =>{
console.error(error);
});
}
render() {
var style = require("./styles.js");
if(this.state.isLoading){
return(
<View style={{flex: 1, padding: 20}}>
<ActivityIndicator/>
</View>
)
}
return (
<View style={style.container}>
<Header text="Daily Quote" />
<View style={style.textContainer}>
<Text
adjustsFontSizeToFit
numberOfLines={3}
style={style.textStyle}
>
{this.state.dataSource.quote}
</Text>
<Text
adjustsFontSizeToFit
numberOfLines={1}
style={style.textStyle}
>
{this.state.dataSource.author}
</Text>
</View>
</View>
);
}
}

You are not invoking loadingQuoteFromUrl anywhere in your App. For fetch operations componentDidMount is a suitable lifecycle method. So, you can use it. But first, you should bind this function in order to use this context. You can do this in the constructor or define it as an arrow function without binding.
class SingleQuote extends React.Component {
constructor(props) {
super(props);
this.state = {
isLoading: true
};
this.loadingQuoteFromUrl = this.loadingQuoteFromUrl.bind(this);
}
componentDidMount() {
this.loadingQuoteFromUrl();
}
loadingQuoteFromUrl() {
return fetch("https://talaikis.com/api/quotes/random/")
.then(response => response.json())
.then(responseJson => {
this.setState(
{
isLoading: false,
dataSource: responseJson
},
function() {}
);
})
.catch(error => {
console.error(error);
});
}
render() {
if (this.state.isLoading) {
return <div>Loading...</div>;
}
return (
<div>
<div>
<p>{this.state.dataSource.quote}</p>
<p>{this.state.dataSource.author}</p>
</div>
</div>
);
}
}
ReactDOM.render(<SingleQuote />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>

class SingleQuote extends React.Component {
constructor(props) {
super(props);
this.state = {
isLoading: true
};
}
componentDidMount() {
this.loadingQuoteFromUrl();
}
loadingQuoteFromUrl = () => {
return fetch("https://talaikis.com/api/quotes/random/")
.then(response => response.json())
.then(responseJson => {
this.setState(
{
isLoading: false,
dataSource: responseJson
},
function() {}
);
})
.catch(error => {
this.setState(
{
isLoading: false,
}
console.error(error);
});
}
render() {
const { isLoading } = this.state;
const { dataSource } = this.props;
if (isLoading) {
return <div>Loading...</div>;
}
return (
<div>
<div>
<p>{dataSource.quote}</p>
<p>{dataSource.author}</p>
</div>
</div>
);
}
}
ReactDOM.render(<SingleQuote />, document.getElementById("root"));

Related

I have this issue undefined is not an object (evaluating 'this.state.dataSource.map')

I want to display a list of places from a online json url.
import React, { Component } from "react";
import {
View,
StyleSheet,
Dimensions,
Image,
StatusBar,
TextInput,
TouchableOpacity,
Text,
Button,
Platform,
Alert,
FlatList,
ActivityIndicator,
} from "react-native";
let url = "https://cz2006api.herokuapp.com/api/getAll";
let url2 = "";
export default class ClinicComponent extends Component {
constructor(props) {
super(props);
this.state = {
isLoading: true,
dataSource: null,
};
}
componentDidMount() {
return fetch("https://cz2006api.herokuapp.com/api/getAll")
.then((response) => response.json())
.then((responseJson) => {
this.setState({
isLoading: false,
dataSource: responseJson.data.data,
});
})
.catch((error) => {
console.log(error);
});
}
render() {
if (this.state.isLoading) {
return (
<View style={styles.container}>
<ActivityIndicator />
</View>
);
} else {
let hospitals = this.state.dataSource.map((val, key) => {
return (
<View key={key} style={styles.item}>
<Text>{val.name}</Text>
</View>
);
});
return (
<View style={styles.item}>
{/* <Text>Content Loaded</Text> */}
{hospitals}
</View>
);
}
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: "#fff",
alignItems: "center",
justifyContent: "center",
},
item: {
flex: 1,
alignSelf: "stretch",
margin: 10,
alignItems: "center",
justifyContent: "center",
borderBottomWidth: 1,
borderBottomColor: "#eee",
},
});
Unfortunately when i tried to run this via expo cli I got an error, saying undefined is not an object
enter image description here
Can anyone help me pls!!! I would just like to have a list of hospitals which are scrollable. Thank you!
The URL of the Json is here: https://cz2006api.herokuapp.com/api/getAll
Simply change your initial state to something like this
this.state = {
isLoading: true,
dataSource: [], // <-- here
};
Your problem is you're using dataSource.map but during api calling your dataSource still stay null until it get its response, and null object have no attribute map. That's the cause of your problem.
remove the return in componentDidMount:
componentDidMount() {
fetch("https://cz2006api.herokuapp.com/api/getAll")
.then((response) => response.json())
.then((responseJson) => {
this.setState({
dataSource: responseJson.data.data,
isLoading: false,
});
})
.catch((error) => {
console.log(error);
});
}
I agree with #Nguyễn's suggestion that your initial state should be an array. However the root of the issue seems to be getting the right properties off off your JSON response.
First, you want responseJson.data instead of responseJson.data.data. That gives me an array and shows a long list but the titles are all blank. That's because your response has Name as an uppercase property but you are accessing name. So you need to change that as well.
export default class ClinicComponent extends Component {
constructor(props) {
super(props);
this.state = {
isLoading: true,
dataSource: [],
};
}
componentDidMount() {
return fetch('https://cz2006api.herokuapp.com/api/getAll')
.then((response) => response.json())
.then((responseJson) => {
this.setState({
isLoading: false,
dataSource: responseJson.data,
});
})
.catch((error) => {
console.log(error);
});
}
render() {
//console.log(this.state.dataSource?.[0]);
if (this.state.isLoading) {
return (
<View style={styles.container}>
<ActivityIndicator />
</View>
);
} else {
return (
<View style={styles.item}>
{/* <Text>Content Loaded</Text> */}
{this.state.dataSource.map((val, key) => (
<View key={val._id} style={styles.item}>
<Text>{val.Name}</Text>
</View>
))}
</View>
);
}
}
}
You are fetching a huge amount of data and you probably want some sort of pagination with infinite scrolling. It is extremely slow to load due to the huge payload that we are fetching.
You also have double-escape problem in the JSON response inside the geocodingData section. You want to return this data as an object but it is an escaped string with lots of \" instead.

Trouble display name property from axios fetched json object

https://codesandbox.io/s/currying-voice-toq9t - I am trying to save the json object into the component state, then render the name into the browser.
getProfile() {
axios
.get(
"https://cors-anywhere.herokuapp.com/" +
"https://phantombuster.s3.amazonaws.com....."
)
.then(response => {
this.setState({
profile: {
name: response.data.name
}
});
})
.catch(error => this.setState({ error, isLoading: false }));
}
Your Response data is an array form so,You need to give Index.I hope it will helps you.
getProfile() {
axios
.get(
"https://cors-anywhere.herokuapp.com/" +
"https://phantombuster.s3.amazonaws.com/YRrbtT9qhg0/NISgcRm5hpqtvPF8I0tLkQ/result.json"
)
.then(response => {
this.setState({
profile: {
name: response.data[0].name
}
});
})
.catch(error => this.setState({ error, isLoading: false }));
}
The response.data is an array where in first position there is the information that you are looking for, so the setState should be like this:
this.setState({
profile: {
name: response.data[0].name
}
});
or
const [obj] = response.data;
this.setState({
profile: {
name: obj.name
}
});
Your response.data returns an array.so you need to traverse it inside a loop.
import React from "react";
import ReactDOM from "react-dom";
import axios from "axios";
export class Profile extends React.Component {
constructor(props) {
super(props);
this.state = { profile: [] };
}
componentDidMount() {
this.getProfile();
}
getProfile() {
axios
.get(
"https://cors-anywhere.herokuapp.com/" +
"https://phantombuster.s3.amazonaws.com/YRrbtT9qhg0/NISgcRm5hpqtvPF8I0tLkQ/result.json"
)
.then(response => {
console.log("response: ", response)
this.setState({
profile: response.data
});
})
.catch(error => this.setState({ error, isLoading: false }));
}
render() {
let { name } = this.state.profile;
const { error } = this.state;
return (
<div className="App">
<header className="App-header">
<h1 className="App-title">Profile</h1>
{error ? <p>{error.message}</p> : null}
</header>
<div className="App-feeds" />
<div className="panel-list">
{this.state.profile.map((element) => <p>First Name: {element.name}</p>)}
</div>
</div>
);
}
}
const rootElement = document.getElementById("root");
ReactDOM.render(<Profile />, rootElement);

Parsing JSON with react native, looping through

i am trying to parse a json file by displaying all the names in the clubs
the json file is https://raw.githubusercontent.com/openfootball/football.json/master/2017-18/it.1.clubs.json
my current code i have is
constructor(props) {
super(props);
this.state = {
isLoading: true,
dataSource: null,
}
}
componentDidMount() {
return fetch('https://raw.githubusercontent.com/openfootball/football.json/master/2017-18/it.1.clubs.json')
.then ( (response) => response.json() )
.then ( (responseJson) => {
this.setState({
isLoading: false,
dataSource: responseJson.clubs,
})
})
.catch((error) => {
console.log(error)
});
}
render() {
if (this.state.isLoading) {
return (
<View style = {styles.containter}>
<ActivityIndicator/>
</View>
)
} else {
return (
<View>
<Text>{this.state.dataSource.name}</Text>
</View>
)
I just want to loop through to display all the names in the clubs
Try this:
Couple of edits: Changing the initial state of dataSouce value as an array, this is to ensure it doesn't throw can't read property map of undefined.
You don't need to return the fetch call, because you don't need a promise to returned.
EDIT: Added a loading text before all the clubs are loaded.
import React from "react";
import ReactDOM from "react-dom";
import "./styles.css";
class App extends React.Component {
state = {
isLoading: false,
dataSource: []
};
componentDidMount() {
this.setState({ isLoading: true }, () => {
fetch(
"https://raw.githubusercontent.com/openfootball/football.json/master/2017-18/it.1.clubs.json"
)
.then(response => response.json())
.then(responseJson => {
console.log(responseJson);
this.setState({
isLoading: false,
dataSource: responseJson.clubs
});
})
.catch(error => {
this.setState({ loading: false });
console.log(error);
});
});
}
render() {
return (
<div className="App">
<h1>Club Names</h1>
{this.state.isLoading ? (
<h1>Loading Clubs...</h1>
) : (
this.state.dataSource.map(data => <h2 key={data.key}>{data.name}</h2>)
)}
</div>
);
}
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
Sandbox Link: https://codesandbox.io/s/throbbing-dream-7lpcm?fontsize=14

Not able to fetch data from API endpoint in ReactJS?

I have created REST API endpoint i.e localhost:5000/api/match/:match_idNow I want to fetch data from this endpoint and display it on frontend but I am getting undefined error.
In server.js :
//Get a particular match stats
app.get('/api/match/:match_id', (req, res) =>{
let match = req.params.match_id;
matches.findOne({id: parseInt(match)}).then(Match =>{
res.json(Match);
});
});
In matchinfo.js :
import React, { Component } from 'react';
class Matchinfo extends Component {
constructor(props){
super(props);
this.state = {
info:[],
loading:true
};
}
componentDidMount(){
fetch('api/match/:match_id')
.then(res => res.json())
.then(res => {
console.log(res)
this.setState({
info:res,
loading:false
})
})
}
render() {
if (this.state.loading) {
return <img src="https://upload.wikimedia.org/wikipedia/commons/b/b1/Loading_icon.gif" />
}
return (
<div>
<p class="match">MATCH {info.id}</p>
<h4>{info.team1}</h4>
<p>VS</p>
<h4>{info.team2}</h4>
<div class="winner">
<h3>WINNER</h3>
<h4>{info.winner}</h4>
</div>
</div>
);
}
}
export default Matchinfo;
In matchinfo component I am getting failed to compile after loader is finished spinning see screenshot for more clarification.
JSON Response :
Try below updated code. It should work as you expected
import React, { Component } from 'react';
class Matchinfo extends Component {
constructor(props){
super(props);
this.state = {
info:[],
loading:true
};
}
componentDidMount(){
fetch('api/match/:match_id')
.then(res => res.json())
.then(res => {
console.log(res)
this.setState({
info:res,
loading:false
})
})
}
renderLoading(){
<img src="https://upload.wikimedia.org/wikipedia/commons/b/b1/Loading_icon.gif" />
}
render() {
const {info} = this.state;
return (
<div>
{this.state.loading ? this.renderLoading(): ''}
{this.state.info.length > 0 && (
<div>
<p class="match">MATCH {info.id}</p>
<h4>{info.team1}</h4>
<p>VS</p>
<h4>{info.team2}</h4>
<div class="winner">
<h3>WINNER</h3>
<h4>{info.winner}</h4>
</div>
</div>
)}
</div>
);
}
}
export default Matchinfo;

i am trying to fetch a Post request but im not getting any value and my app stuck on (loading menu...) i don't know what to do

this is my code
so in the fetch() function i am getting the response but i am nit getting any object or values and my app stuck at (loading view...) function
var REQUEST_URL = 'http://awaissaleem.com/json/api.php';
class test extends Component {
constructor(props) {
super(props);
this.state = {
menu: null,
};
}
componentDidMount() {
this.fetchData();
}
fetchData() {
fetch(REQUEST_URL, {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
menu : 'menu',
active : '1',
})
}).then((response) => response.text())
.then((responseData) => {
this.setState({
menu: responseData.Response,
});
})
.catch((error) => {
console.warn('error',error);
})
.done();
}
render() {
if (!this.state.menu) {
return this.renderLoadingView();
}
var menus = this.state.menu[0];
console.log('menus',menus);
return this.renderMovie(menus);
}
renderLoadingView() {
return (
<View style={styles.container}>
<Text>
Loading menu...
</Text>
</View>
);
}
renderMovie(menus) {
return (
<View style={styles.container}>
<View style={styles.rightContainer}>
<Text style={styles.title}>{menus.menu_type}</Text>
<Text style={styles.year}>{menus.menu_no}</Text>
</View>
</View>
);
}
}
so please point me out where i am missing something..