React fetch api data not being displayed - reactjs

I have a simple fetch request that runs only on the first render. When I update the state with the data and try to map through it nothing is shown. For reference the data I am given back is just one entry. Using .map it should for each entry ( which is 1) display a bullet but nothing is shown.
{quote: "I'm the new Moses"}
import logo from './logo.svg';
import {useState,useEffect} from 'react';
import './App.css';
function App() {
const [users, setUsers] = useState([])
const fetchData = () => {
fetch("https://api.kanye.rest/")
.then(response => {
return response.json()
})
.then(data => {
console.log(data)
setUsers(data)
})
}
useEffect(() => {
fetchData()
}, [])
return (
<div className="App">
<body className='App'>
<div>
{users.length > 0 && (
<ul>
{users.map(user => (
<li>{user.quote}</li>
))}
</ul>
)}
</div>
</body>
</div>
);
}
export default App;

The response value {quote: "I'm the new Moses"} is an object, not an array. It can't be mapped.
Place the response value in an array when saving.
const fetchData = () => {
fetch("https://api.kanye.rest/")
.then(response => {
return response.json();
})
.then(data => {
console.log(data);
setUsers([data]);
});
};

The result you got isn't an array, it's an object. It can't be mapped. However, you can achieve your expected behaviour in many ways. One of them is just put data into an array while setting user.
setUsers([data])

Related

React cant fetch data from API

I want to fetch data from given API(link is censored in code example), but cant manage to to display product.name from my Api fetch.
import { useState, useEffect } from "react";
import axios from "axios";
function DataFetching() {
const [posts, setPosts] = useState([]);
useEffect(() => {
axios
.get("https://CENSORED/")
.then((res) => {
console.log(res);
setPosts(res.data);
})
.catch((err) => {
console.log(err);
});
}, []);
return (
<div>
<div>
{posts.map((post) => (
<h1>{post.product.name}</h1>
))}
</div>
</div>
);
}
Errors
The error is because the posts array is empty initially you need to check first if the array has some data then perform a map
setPosts(res.data.product)
{posts?.map((post) => (
<h1>{post.name}</h1>
))}
or you can use conditional like this
{ posts.length > 0
? posts.map((post) => (
<h1>{post.name}</h1>
))
: <Your custom message/>
}
res.data is indicated to be an object in the console.log. the map method will only work on arrays. If you were expecting an array, make sure you aren't hitting the "detail" endpoint, which would return specific information about a post.

Getting data with axios but unable to display with html

I am trying to display a list of towns or departments from an API, I can display the data with console.log but when i put it in html its not working.
here's my ListTown.js:
import React, { useEffect, useState } from "react";
import api from "./api";
function ListTowns() {
const DEPARTEMENTS = "/get/location/departements";
const [departements, setDepartements] = useState([]);
useEffect(() => {
const fetchData = async () => {
const response = await api.get(DEPARTEMENTS).then((response) => {
setDepartements(response.data.data.departements);
});
};
fetchData();
}, []);
return (
<div>
<ul>
{departements.map((dep) => {
<li key={dep.id}>{dep.name}</li>;
})}
</ul>
</div>
);
}
export default ListTowns;
console log (dep.name) gives this result console.log(dep.name)
You forgot to return the data out of your .map method, so right now it's returning undefined for each element.
{departements.map((dep) => {
return <li key={dep.id}>{dep.name}</li>;
})}

How to render the sorted array of objects using UseMemo ReactHooks

I'm trying to render the sorted array of objects using ReactHooks i have used useMemo for the same and redux as well. Could someone suggest me the best practies for it. Any suggestions on what am i doing wrong here?
I have put the post.js below as well.
I'm trying to render the sorted array of objects using ReactHooks i have used useMemo for the same and redux as well. Could someone suggest me the best practies for it. Any suggestions on what am i doing wrong here?
Thanks
HomePage.js
import React, { useState, useEffect, useMemo } from "react";
import Post from "../../Components/Post/Post";
import "./HomePage.css";
import axios from "axios";
const HomePage = () => {
const [posts, setPosts] = useState("");
let config = { Authorization: "................" };
const url = ".........................";
useEffect(() => {
AllPosts();
}, []);
const AllPosts = () => {
axios
.get(`${url}`, { headers: config })
.then((response) => {
const allPosts = response.data.articles;
console.log(response);
})
.catch((error) => console.error(`Error: ${error}`));
};
const newPostsByTitle = useMemo(() => {
allPosts.sort((a, b) => a.title.localeCompare(b.title)), [posts];
});
return (
<div className="home">
<div className="select">
<select
name="slct"
id="slct"
onChange={(e) => newPostsByTitle(e.target.value)}
></select>
</div>
<Post className="Posts" posts={posts} key={posts.title} />
</div>
);
};
export default HomePage;
Post.js
import React from "react";
import "./Post.css";
import { Fragment } from "react";
const Post = (props) => {
const displayPosts = (props) => {
const { posts } = props;
if (posts.length > 0) {
return posts.map((post) => {
return (
<Fragment>
<div className="Post" key={post.title}>
<img
src={post.urlToImage}
alt="covid"
width="100%"
className="img"
/>
<h5 className="title"> {post.title}</h5>
<p className="author"> {post.author}</p>
<p className="description"> {post.description}</p>
</div>
</Fragment>
);
});
}
};
return <div className="Posts">{displayPosts(props)}</div>;
};
export default Post;
You have a incorrect understanding of what the axios call dos I think.
This is just a function that on trigger will download the data, but you need to store it somewhere (e.g. posts) and use these posts instead of the api call:
const [posts, setPosts] = useState([]); // Use an empty array as defualt so it does work without data before the call
...
const AllPosts = () => {
axios
.get(`${url}`, { headers: config })
.then((response) => {
const allPosts = response.data.articles;
setPosts(allPosts) ?? You need to save the posts somewhere, since allPosts is not accessible outside of this function. Sicne you already have a useState, save them there
console.log(response);
})
.catch((error) => console.error(`Error: ${error}`));
};
const newPostsByTitle = useMemo(() => {
return posts.sort((a, b) => a.title.localeCompare(b.title)), [posts]; // Using {} requeores the return keyword, if you omit the {} you dont need the return statement
}); // Now access the posts saved in state to sort them
Also the key in <Post className="Posts" posts={posts} key={posts.title} /> does not work, since posts is an array not an object. So remove it.

How to fetch data from restAPI and from localStorage at a time?

What I am doing is to load data from my local storage which I have fetched from https://jsonplaceholder.typicode.com/users. I am trying to create a react application in which I have added multiple users as a friend just like facebook. my friend list is in the file called UserInfo.js which code I have given bellow. then I tried to show friends corresponding to their id by comparing with the id which I tried to find from api call so that this can show me the matching users.
You can find my project here: https://codesandbox.io/s/elastic-dream-mp3is?file=/src/App.js
import React, { useState } from "react";
import "./UserInfo.css";
import { useEffect } from "react";
import fakedata from "../../fakedata";
import { getDatabaseCart } from "../../utilities/databaseManager";
const UserInfo = () => {
// // using fakedata
// const [users, setUsers] = useState(fakedata);
// // declaring state while calling api
const [users, setUsers] = useState([]);
// declaring state while loading data from local storage
const [friends, setFriends] = useState(users);
// to load data from Api call
useEffect(() => {
fetch("https://jsonplaceholder.typicode.com/users")
.then((res) => res.json())
.then((data) => setUsers(data));
}, []);
// to load data from local storage
useEffect(() => {
const savedFriends = getDatabaseCart();
const friendsId = Object.keys(savedFriends);
const countFriends = friendsId.map((key) => {
const friend = friends.find((fd) => fd.id == key);
// console.log(friend);
return friend;
});
setFriends(countFriends);
}, [friends]);
// console.log(friends);
// console.log(users);
return (
<div className="userInfo-container">
<div className="userInfo">
{friends.map((friend) => (
<div>
<h4>Name: {friend.name}</h4>
</div>
))}
</div>
</div>
);
};
export default UserInfo;
I have created fakedata collecting data from jsonplaceholder and tested according to above method and it worked perfectly. but when I tried to load data API call, I got the following error:
the first error indicates that it can not read property of name which I tried to return from local Storage after matching the id with api call.
2.second error denotes which I can't understand in my case. I have tried abortCall to handle this error. the error gone but my problem still exits. what can I do now????
With hooks:
import React, { useState } from "react";
//import "./UserInfo.css";
import { useEffect } from "react";
import fakedata from "../../fakedata";
import { getDatabaseCart } from "../../utilities/databaseManager";
const UserInfo = () => {
// // using fakedata
// const [users, setUsers] = useState(fakedata);
// // declaring state while calling api
const [users, setUsers] = useState([]);
// declaring state while loading data from local storage
const [friends, setFriends] = useState([]);
// to load data from Api call
useEffect(() => {
fetch("https://jsonplaceholder.typicode.com/users")
.then((res) => res.json())
.then((data) => setUsers(data));
}, []);
// to load data from local storage
useEffect(() => {
const savedFriends = getDatabaseCart();
const friendsId = Object.keys(savedFriends);
setFriends(friendsId);
}, []);
// console.log(friends);
// console.log(users);
return (
<div className="userInfo-container">
<div className="userInfo">
{users.length > 0 && friends.map((friendId) => {
const friend = users.find(user => user.id === parseInt(friendId));
return (
<div>
<h4>Name: {friend && friend.name}</h4>
</div>
)})}
</div>
</div>
);
};
export default UserInfo;
In the render, Friends return [{0:undefined}]. You are not setting friends correctly.
I make a Class version of your UserInfo component. It works like this.
import React from "react";
import { getDatabaseCart } from "../../utilities/databaseManager";
class UserInfo extends React.Component {
state = {
users: [],
friends: []
}
componentDidMount = () => {
this.getDataFromServer();
this.getDateFromLocalStorage();
}
getDataFromServer = () => {
fetch("https://jsonplaceholder.typicode.com/users")
.then((res) => res.json())
.then((data) => this.setState({users:data}));
}
getDateFromLocalStorage = () => {
const savedFriends = getDatabaseCart();
const friendsId = Object.keys(savedFriends);
//console.log(friendsId)
this.setState({friends:friendsId})
}
render() {
const {users, friends} = this.state;
// console.log('users',users, friends);
// console.log('friends', friends);
return (
<div className="userInfo-container">
<div className="userInfo">
{users.length > 0 && friends.map((friendId) => {
const friend = users.find(user => user.id === parseInt(friendId));
return (
<div>
<h4>Name: {friend && friend.name}</h4>
</div>
)})}
</div>
</div>
);
}
}
export default UserInfo;
Note you have a promise for the 'fetch' so at first render and until users are fetched user = [] empty array. To avoid errors it's good to check the length of users before try to map friends.
You can remove the friend check here because if friends array is empty, there is nothing to map.
return (
<div>
<h4>Name: {friend.name}</h4>
</div>
)
Now, it should be a list with ul and li.

Store api response to an array using react useState

I am new to react hooks. I am trying to cast API response into an array using react useState hook. It's giving me empty with the below approach
const [post, setPostArray] = useState([]);
useEffect(() => {
const postparams = { userList: result };
axios
.get(environment._urlPosts, { headers, params: postparams })
.then(posts => {
// storing response data in array
setPostArray(posts.data.post);
console.log(post);
})
.catch(err => {});
}, []);
Then I used the below approach and I was able to see data is printing in the console log
axios.get(environment._urlPosts, { headers, params: postparams }).then(posts => {
// storing response data in array
for (let obj of posts.data.post) {
post.push(obj)
}
setPostArray(post)
console.log(post)
But when I try to iterate this post array in my JSX, it's giving me empty array.
</div>
{/* array length */}
{post.length}
{post.map(post =>
<div className="card">
<Post username={post.username} fullname={post.fullname} postedTime={post.postedTime} postContent='Hi' tweeterLike={post.tweeterLike} />
</div>
)}
Can you please help me to resolve this?
Here is a minimal Example of what you are trying to achieve.
This is the working code:
import React, {useEffect, useState} from "react";
import "./styles.css";
export default function App() {
const [post, setPostArray] = useState([])
useEffect(() => {
fetch('https://jsonplaceholder.typicode.com/todos/1')
.then(response => response.json())
.then(json => {
console.log(json);
setPostArray([json]);
})
// setPostArray([{name: 'a'}, {name: 'b'},{name: 'c'}])
},[])
console.log(post)
return (
<div className="App">
{
post.map(item => <div>{item.title} </div>)
}
</div>
);
}
Here is the link to the example in codeSandBox: https://codesandbox.io/s/jovial-snow-773kp

Resources