How to pass props to API URL in React js? - reactjs

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.

Related

How do I change a state after getting data from API?

constructor(props) {
super(props);
this.state = {
message: ""
};
}
async getData() {
this.setState({...this.state})
await axios.get("https://g...")
.then(function(response) {
console.log(response);
this.setState({message: response.data})
}).bind(this)
}
render() {
return (
<div>
{this.state.message}
</div>
);
}
I tried to use this code to get data from the API. However, the message that is printed out is only linked to the original constructor, and the getData() function does not change the state. How should I go around changing the state after getting data?
You should use componentDidMount, and put the function requesting data in componentDidMount life circle.
By the way, you can add a loading to enhance the user experience : )
import React from 'react';
import "./styles.css";
const BASE_URL = 'https://api.github.com';
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
message: ''
}
}
componentDidMount() {
this.getData();
}
async getData() {
try {
const result = await fetch(`${BASE_URL}/repos/facebook/react`);
const toJson = await result.json();
const stringify = JSON.stringify(toJson, null, 2);
this.setState({
message: stringify
})
} catch (error) {
// ignore error.
}
}
render() {
const { message } = this.state;
return (
<div>
{message}
</div>
)
}
}
export default App;
If you are using 'async' and 'await' you don;t have to use then() function
you can write
const data = await axios.get("url")
console.log(data.data)
this.setState({message:data.data})

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

React-JS : Initializing a global variable in componentDidMount but not getting its value in render

Actually I am initializing a variable in componentDidMount and from there printing its value on console. So in the console I am getting the value of variable but when I print the value of variable from render I am getting "undefined".
var data //declaring a global variable
export default class Schemes extends React.Component{
constructor(){
super();
this.response = response
componentDidMount(){
/* Some Computation*/
if(localStorage.getItem('xyz')){
data = response
}
}
render(){
console.log("In render", data);
}
Just tested this and it works, but i wouldn't use global variables. I would use state instead.
import React, { Component } from 'react'
var data = 'my data'
class Test extends Component {
constructor(props) {
super(props)
this.response = 'my response'
}
componentWillMount() {
localStorage.setItem('test', 'w00f')
if (localStorage.getItem('test')) {
data = this.response
}
data = this.response
}
render() {
console.log(data) //my response
return (
<div></div>
)
}
}
export default Test
Here is a better version using state:
import React, { Component } from 'react'
class Test extends Component {
constructor(props) {
super(props)
this.state = {
data: null,
response: 'got reponse'
}
}
componentWillMount() {
localStorage.setItem('test', 'w00f')
if (localStorage.getItem('test')) {
this.setState({ data: this.state.response })
}
}
render() {
console.log(this.state.data) //got reponse
return (
<div></div>
)
}
}
export default Test

React: Http request response not displaying in render()

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>
}

Axios data being returned, but calling code not working

Thanks in advance for reading. I am realtively new to the react and es6 world. I had a working component that used axios to call an api. All good. Re-engineered it to put redundant api call code into a utils and call it from anywhere that needs data. But I cannot figure out why this function call isn't working. Anyone see what I am missing?
Here is the utility function:
import Axios from 'axios';
export function getData(strPath){
var sendToken = {
headers: {'Authorization': 'Token tokenHere'}
};
var sendPath = "http://pathHere.com/api/" + strPath
Axios
.get(sendPath,sendToken)
.catch(function (error) {
//error handling here
})
.then(function (response) {
console.log(response.data.results) //outputs my array of 2 elements
return(response.data.results);
})
};
Here is the calling react component:
import React, { Component } from 'react';
import { getData } from './Utils';
class BoardContainer extends React.Component {
constructor(props){
super(props);
this.state = { positions: [] };
}
componentWillMount(){
var x = getData('positions'); //simplified code for debugging and example
console.log(x); //ISSUE: x is undefined
}
render() {
return(
<div>Testing Rendering Board Container
//rendering code would be here (child component call)
</div>
)
}
}
Utility:
import Axios from 'axios'
export function getData(strPath){
const sendToken = {
headers: {'Authorization': 'Token tokenHere'}
}
const sendPath = "http://pathHere.com/api/" + strPath
return Axios.get(sendPath, sendToken)
};
Component:
import React, { Component } from 'react'
import { getData } from './Utils'
class BoardContainer extends React.Component {
constructor(props){
super(props);
this.state = { positions: [] }
}
componentWillMount(){
getData('positions').then((response) => {
console.log(response)
}).catch((error) => {
console.log(error)
})
}
render() {
return(
<div>Testing Rendering Board Container
//rendering code would be here (child component call)
</div>
)
}
}

Resources