Mapping through Strapi data doesnt work in React - reactjs

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

Related

Getting string from a different function in React

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

ReactJS - Data does not load in dropdown list from axios call

I have a React Component like below:
import axios from "axios";
import React from "react";
export default class PersonList extends React.Component {
state = {
users: [],
};
componentDidMount() {
axios
.get("https://jsonplaceholder.typicode.com/users")
.then((response) => {
// handle success
let thedata = response.data;
this.setState({ thedata });
console.log(thedata);
})
.catch((error) => {
// handle error
console.log(error);
});
}
render() {
return (
<select>
{this.state.users.map((user) => (
<option value={user.id}>{user.name}</option>
))}
</select>
);
}
}
The data shows up on console just fine. But my dropdown stills shows empty. No error whatsoever. What I am missing here?
You are setting state as {thedata:thedata} instead of {users:thedata}. Change it like so :-
componentDidMount() {
axios
.get("https://jsonplaceholder.typicode.com/users")
.then((response) => {
// handle success
let thedata = response.data;
this.setState({users:thedata });
console.log(thedata);
})
.catch((error) => {
// handle error
console.log(error);
});
}

How to create a search component that will search a REST API in ReactJS

I am trying to create a component that will search a REST API through an axios request, and then return a list of the results. Right now, I'm facing an issue where all I am getting when I search is 'undefined' and I have no clue why. Any and all suggestions would be amazing.
Users.js
import React, { Component } from 'react';
import axios from 'axios';
import { search } from './utils';
import Users from './UsersDelete';
class App extends Component {
state = {
users: null,
loading: false,
value: ''
};
search = async val => {
this.setState({ loading: true });
const res = await search(
`https://zuul-stage.whatifops.com/v1/user/email/${val}`
);
const users = await res.data.results;
this.setState({ users, loading: false });
};
onChangeHandler = async e => {
this.search(e.target.value);
this.setState({ value: e.target.value });
};
get renderUsers() {
let users = <h1>There's no movies</h1>;
if (this.state.movies) {
users = <Users list={this.state.users} />;
}
return users;
}
render() {
return (
<div>
<input
value={this.state.value}
onChange={e => this.onChangeHandler(e)}
placeholder='Type something to search'
/>
{this.renderUsers}
</div>
);
}
}
export default App;
User.js
import React from 'react';
import { truncStr } from './utils';
const User = props => {
const { id, email, phone } = props.item;
return (
<div className={classes.Container}>
<div className={classes.VoteContainer}>
<span className={classes.Vote}>{email}</span>
</div>
<div className={classes.Bottom}>
<h3 className={classes.Title}>{truncStr(phone, 19)}</h3>
</div>
</div>
);
};
export default User;
UsersDelete.js
import React from 'react';
import User from './User';
const Users = ({ list }) => {
let cards = <h3>Loading...</h3>;
if (list) {
cards = list.map((m, i) => <User key={i} item={m} />);
}
return (
<div>
<div>{cards}</div>
</div>
);
};
export default Users;
utils.js
import axios from 'axios';
export const truncStr = (string, limit) => {
return string.length > limit
? string
.trim()
.substring(0, limit - 3)
.trim() + '...'
: string;
};
const resources = {};
const makeRequestCreator = () => {
let cancel;
return async query => {
if (cancel) {
// Cancel the previous request before making a new request
cancel.cancel();
}
// Create a new CancelToken
cancel = axios.CancelToken.source();
try {
if (resources[query]) {
// Return result if it exists
return resources[query];
}
const res = await axios(query, { cancelToken: cancel.token });
const result = res.data.results;
// Store response
resources[query] = result;
return result;
} catch (error) {
if (axios.isCancel(error)) {
// Handle if request was cancelled
console.log('Request canceled', error.message);
} else {
// Handle usual errors
console.log('Something went wrong: ', error.message);
}
}
};
};
export const search = makeRequestCreator();
**Update: This is the response info after I called console.log(res) after the search function
A few things wrong with your code:
There is no results property on the data returned from the REST API
You don't need to await on this line: const users = await res.data.results;
There is no movies property on your state
I created a codesandbox to test your solution, here is an updated version: https://codesandbox.io/s/async-browser-tz4p6
I have removed a few things from the User.js file that were not necessary (for my tests)

Data from Axios is coming back undefined React

My GET request with axios returns back undefined in my console. All of my endpoints are good and
working from being tested with postman. My initial state go from pets: [] to pets: "". I think it's how I have my async await function set up to get the response data.
Here's the GET Component code
import React, {
Component
}
from 'react';
import axios from 'axios';
export default class ListPets extends Component {
constructor(props) {
super(props);
this.state = {
pets: [],
isLoaded: false,
}
}
componentDidMount = () => {
this.getPets();
};
getPets = async() => {
const res = await axios.get('http://localhost:5000/pets/');
const pets = res.data;
this.setState({
isLoaded: true,
pets: pets
});
console.log('Data has been received!');
console.log(pets.data)
return pets;
}
render() {
console.log('State: ', this.state);
const {
isLoaded,
} = this.state;
if (!isLoaded) {
return <div> Loading... </div>;
} else {
return (<div></div>);
}
}
}
app.get('/pets', function(req, res){
const resultArray = [];
client.connect(err => {
assert.equal(null, err);
console.log("Connected successfully to server");
const db = client.db(dbName);
const cursor = db.collection('pet').find({});
iterateFunc = (doc,err) => {
assert.equal(null, err);
resultArray.push(doc);
console.log(JSON.stringify(doc, null, 4));
if(err) {
console.log(err)
}
}
cursor.forEach(iterateFunc);
client.close();
res.render('index', {pets: resultArray});
});
});
Your code can only render a Loading message but if the problem is the empty string then my guess is your API is returning an empty string.
Here's your code, slightly modified but working with a JSONPlaceholder API: https://codesandbox.io/s/compassionate-faraday-h9xpg
export default class ListPets extends Component {
constructor(props) {
super(props);
this.state = {
pets: [],
isLoaded: false
};
}
componentDidMount = () => {
this.getPets();
};
getPets = async () => {
const res = await axios.get("https://jsonplaceholder.typicode.com/todos");
const pets = res.data;
this.setState({ isLoaded: true, pets: pets });
};
render() {
const { isLoaded, pets } = this.state;
if (!isLoaded) {
return <div>Loading...</div>;
}
return <>{pets && pets.map(pet => <div key={pet.id}>{pet.title}</div>)}</>;
}
}

this.state.data.map is not a function

I'm making an API call with React and the Facebook Graph API
The API is working fine but the map method is showing
this.state.data.map is not a function
import React, { Component } from 'react';
import axios from 'axios';
class user extends Component {
constructor(props){
super(props);
this.state={
data:[123]
}
}
componentDidMount() {
axios.get("facebook url")
.then(response => {
if (response.status === 200 && response != null) {
this.setState({
data: response.data
});
} else {
console.log('problem');
}
})
.catch(error => {
console.log(error);
});
}
render(){
return (
<div>
{this.state.data.map((item,index) => {
return (
<div key={item.id}>
<h1>{item.message}</h1>
</div>
);
})}
</div>
);
}
}
export default user;

Resources