I have a class that accesses an API and returns the value in the API:
import React from 'react';
class UserList extends React.Component {
constructor(props) {
super(props);
this.state = { customer: [] };
}
componentDidMount() {
fetch('https://surpriserecommenderapi.herokuapp.com/recommend?customer_id=alakbar#gmail.com', {
method: "post",
headers: {
"Content-Type": "application/json"
}
}).then(response => {
// *** Check for HTTP success
if (!response.ok) {
throw new Error(`HTTP error ${response.status}`);
}
// *** Read the body, parse it as JSON
return response.json();
})
.then(({ prediction }) => this.setState({ customer: prediction }))
.catch(error => {
// ...*** handle/report error...
});
}
render() {
const customers = this.state.customer.map((item, i) => (
<div>
<h1>{item}</h1>
</div>
));
return (
<div id="layout-content" className="layout-content-wrapper">
<div className="panel-list">{customers}</div>
</div>
);
}
}
export default UserList;
{customers} returns a string "Rome" to display on the website.
I am trying to call this in App.js. I am able to call UserList and display "Rome" however, I want to create an if statement that checks what the value of what is displayed. Like this:
const recommended = <UserList></UserList>
console.log(recommended);
const recommendedPackage = () => {
if(recommended === "Roam in Rome"){
return(
<div>Recommended package: Roam in Rome</div>
)
} else {
return(
<div>No recommended package</div>
)
}
}
Any help would be appreciated!
I believe you should implement the required logic in the UserList class, with some sort of conditional rendering. Maybe something like:
class UserList extends React.Component {
...
parseCustomers() {
return (
this.state.customers.map(item => {
if (item === "Rome") {
// logic here
} else {
// logic here
}
});
);
}
render() {
const customers = this.parseCustomers();
return (
...
);
}
}
Related
I was following the documentation on strapi and react but i get this console error:
this.state.restaurants.map is not a function
If i console log the data it gives me this response
But trying to display them on frontend its not working
This is with the Fetch method
import React from "react";
class App extends React.Component {
state = {
restaurants: [],
error: null,
};
componentDidMount = async () => {
const parseJSON = (resp) => (resp.json ? resp.json() : resp);
const checkStatus = (resp) => {
if (resp.status >= 200 && resp.status < 300) {
return resp;
}
return parseJSON(resp).then((resp) => {
throw resp;
});
};
const headers = {
"Content-Type": "application/json",
};
try {
const restaurants = await fetch("http://localhost:1337/api/restaurants", {
method: "GET",
headers: headers,
})
.then(checkStatus)
.then(parseJSON);
this.setState({ restaurants });
} catch (error) {
this.setState({ error });
}
};
render() {
const { error, restaurant } = this.state;
if (error) {
return <div>An error occured: {error.message}</div>;
}
return (
<div className="App">
<ul>
{this.state.restaurants.map((restaurant) => (
<li key={restaurant.id}>{restaurant.name}</li>
))}
</ul>
</div>
);
}
}
export default App;
This is Axios method
import React from 'react';
import axios from 'axios';
class App extends React.Component {
// State of your application
state = {
restaurants: [],
error: null,
};
// Fetch your restaurants immediately after the component is mounted
componentDidMount = async () => {
try {
const response = await axios.get('http://localhost:1337/api/restaurants');
this.setState({ restaurants: response.data });
} catch (error) {
this.setState({ error });
}
};
render() {
const { error, restaurant } = this.state;
// Print errors if any
if (error) {
return <div>An error occured: {error.message}</div>;
}
return (
<div className="App">
<ul>
{this.state.restaurants.map(restaurant => (
<li key={restaurant.id}>{restaurant.name}</li>
))}
</ul>
</div>
);
}
}
export default App;
My strapi roles on Public have the checked mark to find and findOne the same as on this documentation.
Console log of the response
You get restaurants from response.data but the response have an object
with data: { data: ... }.
Solution:
this.setState({ restaurants: response.data.data });
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 }));
}
I need help to display the data from the API.
When i try to get the data with map i get an error. TypeError: userdata.map is not a function
import React from "react";
import axios from "axios";
export class HighscoreList extends React.Component {
constructor(props) {
super(props);
this.state = {
users: ""
};
}
componentDidMount() {
axios
.get("https://schnitzeljagdar.herokuapp.com/users/getAllUser")
.then(response => {
console.log(response.data);
})
.catch(error => {
console.log(error);
});
}
render() {
return (
<React.Fragment>
<h2>User</h2>
{this.state.users}
</React.Fragment>
);
}
}
Try this https://codesandbox.io/s/wonderful-cherry-63ee9
export default class HighscoreList extends React.Component {
state = {
users: []
};
componentDidMount() {
axios
.get("https://schnitzeljagdar.herokuapp.com/users/getAllUser")
.then(res => this.setState({users:[res.data]}))
.catch(error => {
console.log(error);
});
}
render() {
const {users} = this.state;
let array = users[0]?Object.values(users[0]):[];
console.log(array)
return (
<React.Fragment>
{array.map((arr,index)=>
<div key={index}>
<h2>{arr.username}</h2>
<p>{arr.email}</p>
</div>
)}
</React.Fragment>
);
}
}
import React, { Component } from "react";
import axios from "axios";
class Abc extends Component {
constructor(props) {
super(props);
this.state = { descriptions: [] };
}
componentDidMount() {
axios
.get("https://jsonplaceholder.typicode.com/users")
.then(response => {
this.setState({ descriptions: response.data });
if (response.data) {
var rdata = response.data;
for (var r = 0; r < rdata.length; r++) {
if (r === 0) {
// console.log(rdata[r]);
// const {rdata} this.dataEle = rdata[r]
console.log(this.dataEle.name);
}
}
}
})
.catch(error => {
console.log(error);
});
}
render() {
const { dataEle } = this.setState;
return (
<div>
{dataEle.map((description, index) => (
<p key={index}>{description.description}</p>
))}
</div>
);
}
}
export default Abc;
dataEle is undefined in the first render (and any subsequent renders before it is fetched). You also don't destructure it correctly in your render function. I think you likely meant to destructure descriptions instead.
import React, { Component } from "react";
import axios from "axios";
class Abc extends Component {
constructor(props) {
super(props);
this.state = {
descriptions: [],
};
}
componentDidMount() {
axios
.get("https://jsonplaceholder.typicode.com/users")
.then(response => {
this.setState({ descriptions: response.data });
// if (response.data) {
// var rdata = response.data;
// for (var r = 0; r < rdata.length; r++) {
// if (r === 0) {
// // console.log(rdata[r]);
// // const {rdata} this.dataEle = rdata[r]
// console.log(this.dataEle.name);
// }
// }
// }
})
.catch(error => {
console.log(error);
});
}
render() {
const { descriptions } = this.state;
return (
<div>
// {descriptions.map((description, index) => (
// <p key={index}>{description.description}</p> // response data objects don't have a description property!
// ))}
{descriptions[1] && descriptions[1].name}
</div>
);
}
}
export default Abc;
Also, the response data shape doesn't have a description property on it, but TBH I'm not really sure what you're even trying to do with the for-loop, it throws an error.
Quite a few problems in your code.
Presumably you intended:
const { dataEle } = this.setState;
to be
const { descriptions = [] } = this.state;
Please try that:
class Abc extends Component {
constructor(props) {
super(props);
this.state = {
descriptions: [] ;
}
}
componentDidMount() {
axios
.get("https://jsonplaceholder.typicode.com/users")
.then(response => {
this.setState({ descriptions: response.data });
})
.catch(error => {
console.log(error);
});
}
//for mapping**
return (
<div>
{this.sate.descriptions.map((description, index) => (
<p key={index}>{description.description}</p>
))}
</div>
);
}
}
I'm using a callback from axios.get to set the state of a React component. The data property of the response contains an array of objects which I use to set state.
When I log the state property to the console there are no issues and I can see the array of objects. However if I try to log one of those objects individually I get the error:
Cannot read property '0' of null at ResponsiveTable.render
Below is the code for my component:
class ResponsiveTable extends React.Component {
constructor (props) {
super(props)
this.state = {
returnedQuery: null
};
}
componentDidMount() {
axios.get('/api/latestLeads')
.then((response) => {
this.setState({
returnedQuery: response.data
});
})
.catch(function (error) {
console.log(error);
});
}
render() {
console.log(this.state.returnedQuery[0]);
return (
<div>
<h1>test</h1>
</div>
);
}
}
Sure at first render your returnedQuery is null so you are getting this error.
If you want to use this.state.returnedQuery[0] check if it's exist and it's length > 0:
render() {
if (this.state.returnedQuery && this.state.returnedQuery.lenth > 0){
return (
<div>
{this.state.returnedQuery.map(...)}
</div>
);
} else {
return <div>loading data...</div>
}
}
You could try this:
class ResponsiveTable extends React.Component {
constructor (props) {
super(props)
this.state = {
returnedQuery: null
};
this.getData();
}
getData = () => {
axios.get('/api/latestLeads')
.then((response) => {
this.setState({
returnedQuery: response.data
}, () => {console.log(this.state.returnedQuery);}); //What does this console.log() say?
})
.catch(function (error) {
console.log(error);
});
}
render() {
console.log(this.state.returnedQuery[0]);
return (
<div>
<h1>test</h1>
</div>
);
}
}
I found the solution which was quite similar to Andrew's above, I used the component's internal state to determine whether the axios.get method had returned. Below is the working code, I'm now able to access elements within the returned array and their properties.
class ResponsiveTable extends React.Component {
constructor (props) {
super(props)
this.state = {
returnedQuery: null
};
}
componentDidMount() {
const self = this;
// let returnedQuery;
axios.get('/api/latestLeads')
.then((response) => {
self.setState({
returnedQuery: response.data
});
console.log(response.data);
})
.catch(function (error) {
console.log(error);
});
}
render() {
return (
<div>
<h1>{'This will always render'}</h1>
{ this.state && this.state.returnedQuery &&
<div>{this.state.returnedQuery[0].email}</div>
}
</div>
)
}
}