I have a function which calls an axios.post, this function returns the obejct to the main react App, which should then save it / show it on the screen.
The return of the "postData" function (in API) looks like this:
return axios.post(url, object).then((res) => res.data);
In the main react app, I have:
async postData (file1, file2, algorithm) {
this.setState({
anomalies: await api.postData(file1, file2, algorithm)
}, () => { console.log(this.state.anomalies); }
)
}
When I console.log the anomalies (as in code), I get undefined.
In addition, I have a div as:
<div> {this.state.anomalies} <div/>
Which shows relevant content, but after the call doesn't show anything.
If I do:
axios.post(url, object).then((res) => console.log(res.data);
I get the correct object printed. So then how can I pass this object in the correct way to the React app?
Thanks!
App.js file
import React from "react";
import API from "./API";
export default class App extends React.Component {
constructor(props) {
super(props);
this.state = { anomalies: null };
}
post = async () => {
this.setState(
{
anomalies: await API.postData()
},
() => {
console.log(this.state.anomalies);
}
);
};
render() {
return (
<div>
<button onClick={this.post}> click</button>
</div>
);
}
}
API.js file
import axios from 'axios'
function postData () {
return axios.get("https://jsonplaceholder.typicode.com/todos/1").then( res => res.data)
}
export default {
postData
}
Related
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 }));
}
hey i am new in the field and want to display the state using the map and i am not able to do so
and there is no problem in the api call through axios so ignore it
my code is
import React, { Component } from 'react';
import axios from 'axios';
const url ='https://www.reddit.com/r/space.json';
class Apicall extends Component {
state={
posts:[],
subr:'space'
};
componentDidMount(){
this.getReddit();
}
getReddit=async()=>{
console.log('getredddit called sir ');
try {
let response=await axios.get(`https://www.reddit.com/r/${this.state.subr}.json`);
let posts=response.data.data.children.map(obj=>obj.data)
this.setState({posts:posts},()=>{console.log(this.state.posts);
})
} catch (error) {console.log(error);}}
render() {
let controlItems=this.state.posts.map(post=>{<h1 id={post.id}>{post.title}</h1>});
return (
<div>
<h1>{`/r/${this.state.subr}`} </h1>
{controlItems}
</div>);
}
}
export default Apicall;
You were iterating wrong on your data. response.data.data.children should be replaced with response.data.children. Implicit return of et controlItems=this.state.posts.map(post=>{{post.title}}); is also wrong.
import React from "react";
import "./styles.css";
export default function App() {
return (
<div className="App">
<Apicall />
</div>
);
}
class Apicall extends React.Component {
state = {
posts: [],
subr: "space"
};
componentDidMount() {
this.getReddit();
}
getReddit = async () => {
console.log("getredddit called sir ");
try {
let response = await fetch(
`https://www.reddit.com/r/${this.state.subr}.json`
);
response = await response.json();
console.log(response);
let posts = response.data.children.map(obj => obj.data);
this.setState({ posts: posts }, () => {
console.log(this.state.posts);
});
} catch (error) {
console.log(error);
}
};
render() {
let controlItems = this.state.posts.map(post => (
<h1 id={post.id}>{post.title}</h1>
));
return (
<div>
<h1>{`/r/${this.state.subr}`} </h1>
{controlItems}
</div>
);
}
}
Main javascript soure code like this,
import React from 'react'
import LoadingScreen from './components/LoadingScreen'
import './js/Login'
import './js/XHR'
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
load: false,
}
}
XHRget = async parameter => {
this.setState({ load: true });
await XHR.send(parameter)
.then(result => {
this.setState({ load: false });
console.log(result);
});
}
render() {
return (
<View>
<LoginScreen />
<LoadingScreen load={this.state.load}></LoadingScreen>
</View>
);
}
}
export default App
I create XHRget() in App.js for control the 'LoadingScreen' component.
XHR.js has two functions. 1) create and return XMLHttpRequest funciton called create() and 2) get data from server function called send().
And now, I want call the function XHRget() from login() in Login.js but, I don't know how to call.
How can I call the function XHRget() from another js file?
Create a new file with what ever name you like and put the function inside then export it.
ex.
export const XHRget = async (parent,parameter) =>
{
parent.setState({load: true});
await XHR.send(parameter)
.then(result => {
parent.setState({load: false});
console.log(result);
});
}
Remember to pass in this when calling it
I have a component that calls api and returns data, url is like this: https://myapi/CLASS_NBR. But right now the api does not get fired and it returns null. I checked the browser network status, there is not api call. Any idea? My code is as below:
import React, { Component } from "react";
import axios from "axios";
class CourseDetail2 extends Component {
state = {
CLASS_NBR: this.props.match.params.CLASS_NBR,
course: null
};
componentDidMount() {
const { CLASS_NBR } = this.state;
this.runSearch();
}
runSearch = async () => {
const response = await axios.get(
`api/${this.props.match.params.CLASS_NBR}`
);
this.setState({ course: response.data });
};
render() {
const course = this.state.course; //null here
return (
<div>
Course Detail: CLASS NBR {this.props.match.params.CLASS_NBR}
////this information is passed in through react-router Link
{course.SUBJECT} //null
CATALOGNO:{course.CATALOG_NBR}//null
</div>
);
}
}
export default CourseDetail2;
I am new to react-redux actually so I just need some help trying to understand any syntactical or logical mistake I am making here...
Basically, I want to display the reports fetched from another server. Function 'fetchNames' handles that and function 'fetchdownloadable' creates a returns a link that allows to pass through authentication and download the report in pdf onClick.
So I debugged on console, and I believe that there is something wrong with the order of execution of the code... when i debug.. i noticed that :
fetchnames is executed first to fetch all report data in json array...
then fetchDownloadable is called for each object in the reports array and that returns 'undefined' value on SampleChild...
then SampleChild is executed with undefined value...
and then we come back to execute the fetchDownloadable function that prints link value on the console and dispatches action on the reducer that returns the 'state' instead of 'action.reports_uri' in the reducer...
Thanks in advance!
SampleParent.js
import React, {Component} from 'react'
import { connect } from 'react-redux'
import { fetchNames, fetchDownloadable } from '../../actions/actions'
import SampleChild from '../ui/SampleChild'
class SampleParent extends Component {
constructor(props) {
super(props);
this.fetchDownloadLink = this.fetchDownloadLink.bind(this)
}
componentDidMount() {
const { dispatch } = this.props
dispatch(fetchNames())
}
fetchDownloadLink(uri){
this.props.dispatch(fetchDownloadable(uri))
}
render() {
return (<div><ul id="myUL">
{this.props.reports.map((report) => (
<li><SampleChild
key={report.id}
label={report.label}
uri={this.fetchDownloadLink("http://localhost:8080/sample"+report.uri+".pdf")}
/></li>))}
</ul></div>
)}
}
function mapStateToProps(state) {
const { reports } = state
return {
reports
}}
export default connect(mapStateToProps)(SampleParent)
SampleChild.js
import React, { Component } from 'react'
export default class SampleChild extends Component {
render() {
const { key, label, uri } = this.props
return (
<div className="inside_SampleChild" id={label}>
{label}
</img>
</div>
)}}
Action.js
import C from '../constants'
import fetch from 'isomorphic-fetch'
export const fetchNames = value => dispatch => {
var obj = { method: 'GET', headers: { 'Authorization': 'Basic ***', 'Accept': 'application/json' },
'credentials': 'include'};
fetch('http://localhost:8080/samplelink', obj)
.then(response => {
if (response.status !== 200) {
throw Error(response.status);
}return response;})
.then((response) => response.json())
.then(resourceLookup => {
var arr = [];
var length = resourceLookup.resourceLookup.length;
for(var i = 0 ; i< length ; i++){
arr.push(resourceLookup.resourceLookup[i]);}
dispatch({
type: C.FETCH_LIST_REPORTS,
reports: arr})}).
catch(error => {
console.log("There was this error" + error);});}
export const fetchReportDownloadable = (uri) => dispatch => {
var obj = {
method: 'GET',
headers: {
'Authorization': 'Basic ***=',
'Accept': 'application/json'
},
'credentials': 'include'
};
fetch(uri, obj)
.then(response => {
if (response.status !== 200) {
throw Error(response.status);
}
return response ;
})
.then((response) => response)
.then(resourceLookup => {
console.log(`resourceLookup URL: ${resourceLookup.url}`)
dispatch({
type: C.FETCH_DOWNLOADABLE,
report_uri: resourceLookup.url
})
}).
catch(error => {
console.log("There was this error" + error);
});}
Reducers.js
import C from '../constants'
import { combineReducers } from 'redux'
export const links = (state=null, action) =>
(action.type === C.FETCH_DOWNLOADABLE) ?
action.report_uri :
state
export const reports = (state=[], action) => {
switch(action.type) {
case C.FETCH_LIST_REPORTS :
return action.reports
default :
return state
}}
const rootReducer = combineReducers({
reports,
links
})
export default rootReducer
I will try explaining what is happening.
First, the first problem you have is that your passing a wrong value, or either undefined value of uri in:
<li>
<SampleChild key={report.id} label={report.label}
uri={this.fetchDownloadLink("http://localhost:8080/sample"+report.uri+".pdf")}
/>
</li>
Here uri is a function, that triggers on the first render, it dispatches the fetchDownloadable(uri) action, it does not return any value however. Hence the uri is undefined.
Secondly, you have C.FETCH_REPORT_DOWNLOADABLE constant used in your reducer. However you never dispatch an action of that type, the action dispatches C.FETCHING_DOWNLOADABLE. Hence the reducer does not do anything really, so the state does not change. My second comment was about C.FETCH_LIST_REPORTS, which is irrelevant for you right now, so I was wrong about that.
What I would do, is create the download link from the server side. Send it back with the report object. This way, you won't need to dispatch two actions to list your reports. Then, I will dispatch my action in componentWillMount(), once it's done fetching the data, the state will be changed - if, again, you have dispatched the correct action - and you will have your reports with the download URL in the same object.
Update
Okay I think that I understand now. What I would do then is to send the uri as string to SampleChild, and then when it mounts I will trigger the fetchDownloadablefunction.
SampleParent
import React, {Component} from 'react'
import { connect } from 'react-redux'
import { fetchNames, fetchReportDownloadable } from '../../actions/actions'
import SampleChild from '../ui/SampleChild'
class SampleParent extends Component {
constructor(props) {
super(props);
this.fetchDownloadLink = this.fetchDownloadLink.bind(this)
}
componentDidMount() {
const { dispatch } = this.props
dispatch(fetchNames())
}
fetchDownloadLink(uri){
this.props.dispatch(fetchReportDownloadable(uri))
}
render() {
return (<div><ul id="myUL">
{this.props.reports.map((report) => (
<li><SampleChild
key={report.id}
label={report.label}
uri={"http://localhost:8080/sample"+report.uri+".pdf"}
download={this.fetchDownloadLink}
/></li>))}
</ul></div>
)}
}
function mapStateToProps(state) {
const { reports } = state
return {
reports
}}
export default connect(mapStateToProps)(SampleParent)
SampleChild
import React, { Component } from 'react'
export default class SampleChild extends Component {
componentDidMount() {
this.props.download(this.props.uri);
}
render() {
const { key, label, uri } = this.props
return (
<div className="inside_SampleChild" id={label}>
{label}
</img>
</div>
)}}
What is supposed to happen now is that you will fetch the reports first in SampleParent then pass the information to SampleChild. Whenever a SampleChild is mounted, it will trigger fetchDownloadable action which in returns download the uri sent to it.