Not able to fetch data from API endpoint in ReactJS? - json

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;

Related

How to use data from a api (json) in react

I am making a simple weather app with react and typescript.
I want to know how to display simple data fetched from a public api in react and typescript. This api is in a json format. URL(https://data.buienradar.nl/2.0/feed/json)
How do you use api data in react?
What I have tried is calling the get forecast function inside a paragraph.
<p>Forecast: {getForecast} </p>
Source code of the forecast component.
import React from 'react';
const Forecast = () => {
function getForecast() {
return fetch("https://data.buienradar.nl/2.0/feed/json")
.then((response)=> response.json())
.then((data) => {return data.forecast})
// .then((data) => {return data});
.catch((error) => {
console.log(error)
})
}
return (
<div>
<h2>Take weatherdata from the api</h2>
<div>
</div>
<button onClick={getForecast}>Take weather data from the api</button>
<p>Forecast: {getForecast}</p>
</div>
)
}
export default Forecast;
UseState() is the react hook method, which helps to achieve it. Check the below code for reference.
import React, { useState } from 'react';
const Forecast = () => {
const [forecast, setForecast] = useState();
function getForecast() {
return fetch("https://data.buienradar.nl/2.0/feed/json")
.then((response)=> response.json())
.then((data) => {return setForecast(data.forecast)})
// .then((data) => {return data});
.catch((error) => {
console.log(error)
})
}
return (
<div>
<h2>Take weatherdata from the api</h2>
<div>
</div>
<button onClick={getForecast}>Take weather data from the api</button>
<p>Forecast: {forecast}</p>
</div>
)
}
export default Forecast;

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

Pass database data from express.js server to react.js component

This is a react app with an express.js backend. I have a mysql database connected to my server.js file and it seems to be connected fine. My issue is I want to pass that data to my react app and display it there.
My server.js database connection
app.get('api/listitems', (req, res) => {
connection.connect();
connection.query('SELECT * from list_items', (error, results, fields) => {
if (error) throw error;
res.send(results)
});
connection.end();
});
So this should grab the 'list_items' records from the database
Below is my react.js code. I would like to display the records under the grocery list h3.
import React, { Component } from 'react';
import './App.scss';
class App extends Component {
constructor(props) {
super(props);
this.state = {
data: ['first item']
};
}
render() {
return (
<div className="App">
<h3>Grocery List</h3>
{this.state.data}
</div>
);
}
}
export default App;
I know this is a simple concept but I am new to backend development. The tutorials I have found have gotten me to this point, but I have had an issue finding one that simply explains how to pass and display data from the backend to frontend.
**index.js**
import React from 'react';
import { render } from 'react-dom';
import App from './components/app';
import { BrowserRouter } from 'react-router-dom'
import { Provider } from 'react-redux';
import store, { history } from './store';
const route = (
<Provider store={store}>
<BrowserRouter>
<App />
</BrowserRouter>
</Provider>
)
render(route,document.getElementById('app'))
**action/listItemAction.js**
export const ListItemSuccess = (data) => {
return {type: 'GET_LIST_ITEMS'};
}
export const getListItems = () => {
return (dispatch) => {
return axios.get('http://localhost:5000/api/listitems')
.then(res => {
dispatch(ListItemSuccess(res));
})
.catch(error=>{
throw(error);
})
};
}
**reducers/listItems.js**
const listItems = (state = [], action) => {
switch(action.type){
case 'GET_LIST_ITEMS':
return action.res.data;
default:
return state;
}
}
export default listItems;
**store.js**
import { createStore, applyMiddleware, compose } from 'redux';
import thunk from 'redux-thunk'
import listItems from './reducers/listItems.js';
const store = createStore(listItems, compose(
applyMiddleware(thunk),
window.devToolsExtension ? window.devToolsExtension() : f => f
));
export default store;
**App.js**
import React, { Component } from 'react';
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import './App.scss';
import getListItems from './action/listItemAction.js
class App extends Component {
constructor(props) {
super(props);
this.state = {
data: [],
isLoading: true,
};
}
componentWillMount() {
this.props.getListItems().then(() => {
this.setState({data: this.props.listItems, isLoading:false});
}).catch(error => {
throw(error);
});
}
render() {
return (
<div className="App">
<h3>Grocery List</h3>
{this.state.isLoading ? <p>Loading...</p>
: this.state.error ? <p>Error during fetch!</p>
: (
<ul>
this.state.data.map(item => <li>{item}</li>)
</ul>
)}
</div>
);
}
}
const mapStateToProps = (state) => {
return {
listItems: state.listItems
};
};
const mapDispatchToProps = (dispatch) => {
return {
getListItems: bindActionCreators(getListItems, dispatch),
};
};
export default connect(mapStateToProps,mapDispatchToProps)(App);
You want to make a GET request to your backend to asynchronously fetch the data. If you want the data when your App component first mounts, you can use fetch in componentDidMount to call to your backend endpoint. Here's an example, with a loading fallback and basic error handling:
class App extends Component {
state = {
data: [],
loading: true,
error: false
}
...
componentDidMount() {
// Pick whatever host/port your server is listening on
fetch('localhost:PORT/api/listitems')
.then(res => { // <-- The `results` response object from your backend
// fetch handles errors a little unusually
if (!res.ok) {
throw res;
}
// Convert serialized response into json
return res.json()
}).then(data => {
// setState triggers re-render
this.setState({loading: false, data});
}).catch(err => {
// Handle any errors
console.error(err);
this.setState({loading: false, error: true});
});
}
render() {
return (
<div className="App">
<h3>Grocery List</h3>
// The app will render once before it has data from the
// backend so you should display a fallback until
// you have data in state, and handle any errors from fetch
{this.state.loading ? <p>Loading...</p>
: this.state.error ? <p>Error during fetch!</p>
: (
<ul>
this.state.data.map(item => <li>{item}</li>)
</ul>
)}
</div>
);
}
}
fetch won't reject on HTTP error status (404, 500), which is why the first .then is a little odd. The .catch will log the response here with the status, but if you want to see the error message from the server, you'll need to do something like this:
if (!res.ok) {
return res.text().then(errText => { throw errText });
}
See See https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch for more information, or explore other data fetching libraries like axios.

fetching of json from url is stuck

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"));