Reputation: 25
My useEffect is getting data from web api. I want to render all posts on home page and trigger again my useEffect when someone create new post. The problem is when I put dependancy on useEffect its start doing endless requests. When I pass empty array as dependancy , when someone create new post it doesnt render on home page until I refresh the page. I read a lot in internet about that problem but still I dont know how to do it. Thanks
function App() {
const [posts, setPosts] = useState([]);
useEffect(() => {
const jwt = localStorage.getItem("jwt");
fetch('https://localhost:44366/api/Posts/getAllPosts',
{
method: "GET",
headers: {
"Content-Type": "application/json",
'Authorization': 'Bearer ' + jwt
},
})
.then(r => r.json()).then(result => setPosts(result));
}, [posts]);
return (
<div >
<Router>
<Header />
<main className="App">
{
posts.map(post => (
<Post keyToAppend={post.CreatedOn} username={post.User.FirstName} title={post.Title} content={post.Content} images={post.ImageUrls} avatarImage={post.User.MainImageUrl} />
))
}
</main>
</Router>
<Footer />
</div>
);
}
Post component :
const Post = ({ keyToAppend, username, title, content, images, avatarImage }) => {
return (
<div className="post" key={keyToAppend}>
<div className="post__header">
<Avatar
className="post__avatar"
alt="avatar"
src={avatarImage}
/>
<h3 className="username">{username}</h3>
</div>
<h1 className="title">{title}</h1>
<p className="content">{content}</p>
<p>
{typeof images != "undefined" ? <ImageSlider slides={images} /> : ""}
</p>
</div>
)
}
export default Post;
Upvotes: 2
Views: 93
Reputation: 1074138
Remove posts
from the dependency array, so it's just []
. That will run the effect once, when the component loads.
useEffect(() => {
const jwt = localStorage.getItem("jwt");
fetch('https://localhost:44366/api/Posts/getAllPosts',
{
method: "GET",
headers: {
"Content-Type": "application/json",
'Authorization': 'Bearer ' + jwt
},
})
.then(r => r.json()).then(result => setPosts(result));
}, []);
// ^^−−−−− remove `posts` here
The reason it runs endlessly with your current code is that your effect callback changes the posts
state member, which triggers the effect again (because posts
is in the dependency array).
You only need to include things in the dependency array that you read in the effect callback. You never read posts
in the effect callback.
Side note: That code is falling prey to the fetch
API footgun I describe here. You need to check r.ok
before calling r.json
(and handle errors):
useEffect(() => {
const jwt = localStorage.getItem("jwt");
fetch("https://localhost:44366/api/Posts/getAllPosts", {
method: "GET",
headers: {
"Content-Type": "application/json",
"Authorization": "Bearer " + jwt
},
})
.then(r => {
if (!r.ok) { // <=================
throw new Error(`HTTP error ${r.status}`);
}
return r.json();
})
.then(result => setPosts(result))
.catch(error => {
// ...handle/report error here...
});
}, []);
Upvotes: 5