React: Http request response not displaying in render() - reactjs

Can someone tell me what is wrong with my code below? I am making an HTTP request to Darksky API using 'superagent' and then trying to display the result in an h2 which isn't working. I tried logging it to console and it works perfectly but if I am trying to display it on the page it doesn't work. Could someone help me out pls, I am new to react and not sure what is going wrong.
import React, { Component } from "react";
import "./Body.css";
import Request from "superagent";
class Body extends Component {
constructor() {
super();
this.getData = this.getData.bind(this);
}
getData() {
var url = this.props.apiUrl;
Request.get(url)
.then(response => {
return(JSON.stringify(response.currently.summary));
})
.catch(error => {});
}
render() {
<div>
<h2>
{this.getData()}
</h2>
</div>
}
}
export default Body;
This is the other file where I am importing Body.js :-
import React, { Component } from "react";
import Body from "./Body";
import "./App.css";
class App extends Component {
render() {
return <Body
apiUrl="https://api.darksky.net/forecast/42a9693aecf45c358afbda0022c5cf65/28.5355,77.3910" />;
}
}
export default App;

You need to set your data in the state of the component, it fire new render:
constructor() {
super();
this.getData = this.getData.bind(this);
this.state = {data: {}}
}
componentDidMount() {
var url = this.props.apiUrl;
Request.get(url)
.then(response => this.setState({data: JSON.stringify(response.currently.summary)}))
.catch(error => {});
}
render(){
console.log("your data", this.state.data);
return <div>test</div>;
}
And work with this data with this.state.data.
I advise you to change getData() function to componentDidMount mehtod.

You should use a life cycle method(componentDidMount) with the use of state. It is recommended to make HTTP calls inside the componentDidMount() method.
constructor() {
super();
this.state = {
result: ''
};
}
componentDidMount(){
var url = this.props.apiUrl;
Request.get(url)
.then(response => {
this.setState({
result: JSON.stringify(response.currently.summary)
});
})
.catch(error => {});
}
render() {
<div>
<h2>
{this.state.result}
</h2>
</div>
}

Related

React HOC with Router not finding page

Hi I am working on a react app with Routing and HOC. I expect to see a page but i get page not found when i know the page is there.
in componentDidMount this.setState, data is shown as undefined but in the HOC wrapper i see the data arrive from the server.
Before I wrapped the page in HOC i could see it rendering content so I know the content exists.
Here is my Page component which is being called via a Route :
import React, { Component } from "react";
import WithBackend from "./WithBackend";
class Page extends Component {
constructor(props) {
super(props);
this.state = { model: null };
}
render() {
if (this.state.model != null) {
return (
<div className="container">
<div className="row">
<div className="col-md">
<h1>{this.state.model.title}</h1>
</div>
</div>
</div>
);
} else {
return (
<div>
<h2>Home</h2>
</div>
);
}
}
componentDidMount() {
const data = this.props.getPage("1");
console.log(data);
this.setState({
model: data,
});
}
}
export default WithBackend(Page);
Here is the HOC component WithBackend: I am not sure if i should be setting the state on this class on in the class that is being wrapped.
When i debug the code in the getPage method, in the setState part i see the data being populated from the backend server.
import React from "react";
import ContentService from "./ContentService";
const WithBackend = (WrappedComponent) => {
class HOC extends React.Component {
constructor() {
super();
this.contentService = new ContentService();
this.getPage = this.getPage.bind(this); // <-- Add this
}
getPage(id) {
this.contentService
.getPage(id)
.then((response) => response.json())
.then((data) => {
this.setState({ model: data });
})
.catch((e) => {
console.log(e);
});
}
render() {
return <WrappedComponent getPage={this.getPage} {...this.props} />;
}
}
return HOC;
};
export default WithBackend;
and here is the contentService which only returns a promise:
class ContentService {
pageUrl = process.env.REACT_APP_BASE_URL + "/pages/";
getPage(id) {
const path = this.pageUrl + id;
const fetchPromise = fetch(path, {
method: "GET",
});
return Promise.resolve(fetchPromise);
}
}
export default ContentService;
Could anyone please advice what i am doing wrong?
Thanks in advance.
getPage is an asynchronous method, that should return a promise:
getPage(id) {
return this.contentService
.getPage(id)
.then((response) => response.json())
.catch((e) => {
console.log(e);
});
}
And then
componentDidMount() {
this.props.getPage("1").then(model => this.setState({ model }));
}

How to pass props to API URL in React js?

i'm new to React and I need help with passing props to API URL. I have two class components -> (MyClass) works fine. However when I use variable from MyClass as props in other class component (MyOtherClass), it seems to work only in "render" part. I mean <div> variable: {variable}, url : {url2}</div> is shown in app as expected but when I try to pass this variable from props to API URL, it is not working and instead the URL looks like this: "http://localhost:55111/status/[object Object]". Any ideas what might cause the problem??
Here's my code:
import React, { Component } from 'react'
import axios from 'axios'
export default class MyClass extends Component {
constructor(props) {
super(props);
this.state = {
data: {}
}
}
componentDidMount() {
axios
.get("http://localhost:55111/start")
.then(response => {
this.setState({
data: response.data
});
console.log(this.state.data);
})
.catch(err => {
this.err = err;
});
}
render() {
const variable = this.state.data.sent
return (
<div>
<h1>Hello worlds</h1>
<p>var: {variable}</p>
<MyOtherClass variable={variable} />
</div>
);
}
}
This is the other class component causing troubles:
class MyOtherClass extends Component {
constructor(props) {
super(props);
this.state = {
data: {}
};
}
async componentDidMount() {
const {variable} = this.props
axios.get(`http://localhost:55111/status/${variable}`)
.then(response => {
this.setState({
data: response
});
console.log(this.state);
})
render() {
const { variable } = this.props
const url2 = `http://localhost:55111/status/${variable}`
return (
<div>variable: {variable}, url : {url2}</div>
);
}
}
import React, { Component } from 'react'
import axios from 'axios'
export default class MyClass extends Component {
constructor(props) {
super(props);
this.state = {
data: {}
}
}
componentDidMount() {
this.getData()
}
async getData() => {
const response = await axios.get("http://localhost:55111/start")
this.setState({data: response.data})
}
render() {
const variable = this.state.data.sent
return (
<div>
<h1>Hello worlds</h1>
<p>var: {variable}</p>
<MyOtherClass variable={variable} />
</div>
);
}
}
Use the async await.

How to pass parameters in API request in React?

I am making an API call in react where from a cryptocurrency API data will be fetched. But I want to get the data for specific cryptocurrencies. I am trying to define some logic inside the fetch request but it's not working. I am trying to add "bitcoin" and "ethereum" as a paramters inside the request.
Code:
import React, { Component } from 'react';
import './App.css';
import Crypto from './Component/Crypto';
class App extends Component {
constructor(){
super();
this.state={
data: [
{
name:'',
id:'',
symbol:'',
price_usd:'',
percent_change_1h:'',
percent_change_24h:'',
percent_change_7d:'',
isLoading:true
},
]
}
this.fetchData=this.fetchData.bind(this);
}
fetchData=()=>{
fetch('https://api.coinmarketcap.com/v1/ticker/?limit=3')
.then((response)=>{
const wanted=['ethereum','bitcoin']
const r=response.data.filter(currency=>
wanted.includes(currency.id))
this.setState({
data:r,
isLoading:false
})})
.catch(err=>alert("error"));
}
componentDidMount(){
this.fetchData();
this.interval = setInterval (() => this.fetchData (), 10*1000)
}
render() {
return (
<div className="App">
<div className="App-header">
{this.state.isLoading?<Loading/>:
<Crypto data={this.state.data}/>
}
</div>
</div>
);
}
}
const Loading=()=>{
return(
<div>
loading...
</div>
);
}
export default App;
try this way :
fetch('https://api.coinmarketcap.com/v1/ticker/?limit=3')
.then((resp) => resp.json())
.then(function(data){
const wanted=['ethereum','bitcoin']
const filtered=data.filter(currency=>{ return wanted.includes(currency.id)
});
console.log(filtered);
}).catch(err=>alert('error'));
learn more about fetch api here : https://scotch.io/tutorials/how-to-use-the-javascript-fetch-api-to-get-data

componentDidMount not firing in React

import React from 'react';
import ReactDOM from 'react-dom';
import $ from 'jquery';
import Post from './components/Post.jsx';
import Feed from './components/Feed.jsx';
class App extends React.Component {
constructor() {
super();
this.state = {
view: 'feed',
collection: ''
}
}
componentDidMount() {
console.log('component did mount')
this.getCollection();
}
async getCollection() {
try {
const response = await fetch('/api/page');
const responseJSON = await response.json();
this.setState({ collection: responseJSON }, () => {
console.log("App Component - getCollection() State Updated", this.state);
});
} catch (error) {
console.log("App Component - getCollection() error", error);
}
}
render() {
return (
<div>
Text
</div>
);
}
}
ReactDOM.render(<App />, document.getElementById('app'));
Can't get component did mount to function. Trying to make an ajax request to my mongodb and render that on the client side. All I need to do now is make a state change setting the collection to the information I get back. I tried using an Ajax request but that didnt work. Now I'm implementing an async fetch call as per the suggestion of another contributor.
the nonworking ajax request:
As of now, componentDidMount is still not being triggered and the collection property of the state is still an empty string.
I would recommend using the Fetch API for AJAX calls and making use of ES6 Async/Await, since importing an entire library just for Ajax seems a bit overkill.
import React from 'react';
import ReactDOM from 'react-dom';
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
collection: ''
}
this.getCollection = this.getCollection.bind(this)
}
componentDidMount() {
console.log('component did mount')
this.getCollection();
}
async getCollection() {
try {
const response = await fetch('/api/blogs');
const responseJSON = await response.json();
this.setState({ collection: responseJSON }, () => {
console.log("App Component - getCollection() State Updated", this.state);
});
} catch (error) {
console.log("App Component - getCollection() error", error);
}
}
render() {
return (
<div>
<h1>Welcome</h1>
</div>
);
}
}
ReactDOM.render(<App /> , document.getElementById('app'));
I'm not sure what you're doing with your render, but I've left it out. Hopefully, this will shed some light on how best to perform what you want.
To get componentDidMount to fire you need the render function. Because first the component renders and then it calls the function componentDidMount.
I think adding this to your class should solve your problem.
render() {
return null;
}

beginner at react.js - rendering component from state which is updated later

I'm trying to test rendering a list component from an JSON object called with fetch, however I suspect the render is called before the JSON is returned as I get an undefined error. Note the debug alert() gets the value, but the render has already error on undefined. How do I handle this? Is there a way to call the render function after the data has been fetched? OR could how would I get the data to render with '?' and then update when the data arrives? Note my if (!object) doesn;t work when called as an inline wrapper - why not - or more impoartanly how would I achive this? Sorry for the begginer questions - I suspect I meant to be using a data framework to bring data for react to display but I wanted to start learning with less frameworks and get the basics. Many thanks! - code is:
import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
class ItemLister extends React.Component {
constructor(props ) {
super(props);
this.state = { items: [] };
}
componentDidMount() {
let url = "http://localhost:8888";
let iterator = fetch(url, {method: 'GET'});
iterator
.then(response => {
//console.log('sss', response)
return response.json();
})
.then(post => {
//console.log(post)
this.state.items = post;
alert(this.state.items.users[3].firstname);
});
}
output(object){
if (!object){
return '?';
}else{
return object;
}
}
render() {
return(
<div>
<div>Items:</div>
<div>{this.output(this.state.items.users[3].firstname)}</div>
</div>
);
}
}
export default ItemLister;
your render function could be something like this:
render() {
const username = (this.state.items === []) ? placeholder : this.output(this.state.items.users[3].firstname;
return(
<div>
<div>Items:</div>
<div>{username}</div>
</div>
);
}
basically, you render a placeholder component until your data arrives, since your data fetch is async and in componentDidMount, so your render will happen initially before you have data.
although you probably want to rethink how this component is constructed in general, why are you accessing specifically users[3]?
Try this code it will help you
import React, { Component } from "react";
import logo from "./logo.svg";
import "./App.css";
class ItemLister extends Component {
constructor(props) {
super(props);
this.state = { items: [], firstname: "" };
}
componentDidMount() {
let url = "http://localhost:8888";
let iterator = fetch(url, { method: "GET" });
iterator
.then(response => {
//console.log('sss', response)
return response.json();
})
.then(post => {
//console.log(post)
this.setState({
items: post,
firstname: this.state.items.users[3].firstname
});
alert(this.state.items.users[3].firstname);
});
}
output(object) {
if (!object) {
return "?";
} else {
return object;
}
}
render() {
return (
<div>
<div>Items:</div>
<div>{this.state.firstname}</div>
</div>
);
}
}
export default ItemLister;

Resources