I'm struggling to get "lovedList" values as the page loads for the first time. When re-rendering, the list is correctly updated. How can I make it so it waits for the list values to render the first objects from useEffect?
import { Post, PostProps } from "./Post";
import { useEffect, useState, useCallback } from "react";
import { api } from "../services/api";
import { useSession } from "next-auth/client";
export function PostList() {
const [session, status] = useSession();
const [loading, setLoading] = useState(true);
const [data, setData] = useState<PostProps[]>([])
const [skip, setSkip] = useState(0)
const take = 3
let list = []
async function getUserPurchases() {
if (session) {
const response = await api.get(`/purchases/${session?.id}`)
response.data.map(purchase => {
list.push(purchase.postId)
})
}
return list
}
async function handleLoadMore() {
setLoading(true)
const lovedList = await getUserPurchases();
setSkip(skip take)
const newPosts = await api.get(`/post?take=${take}&skip=${skip}`)
const formattedData = newPosts.data.map(post => {
console.log(lovedList)
return {
id: post.id,
image: post.image,
institution: post.institution,
title: post.title,
description: post.description,
createdAt: new Date(post.createdAt).toLocaleDateString('pt-BR', {
day: '2-digit',
month: 'long',
year: 'numeric'
}),
loved: lovedList.includes(post.id),
author: {
image: post.author.image,
name: post.author.name,
id: post.author.id
}
}
})
setData([...data, ...formattedData])
setLoading(false)
}
useEffect(() => {
handleLoadMore()
}, [])
if (loading) {
return <h1>Carregando</h1>
}
return (
<main className="flex flex-col md:max-w-3xl xl:max-w-6xl mx-auto text-gray-200 text-6xl ">
{data && data.map(post => (
<Post
key={post.id}
image={post.image}
institution={post.institution}
title={post.title}
description={post.description}
createdAt={post.createdAt}
loved={post.loved}
author={post.author}
id={post.id}
/>
))}
<button
type="button"
className="px-4 py-3 bg-blue-400 rounded-full outline-none flex items-center
justify-center text-sm my-16 mx-auto w-4/12 hover:bg-blue-500
transition-colors duration-200 ease-out"
onClick={handleLoadMore}
>
Carregar Mais
</button>
</main>
);
}
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>
When I load the page, the console.log returns empty arrays. If the next few items load, they console.log the propper list. How can I make it so it load properly when accessing the page for the first time?
Thanks!
CodePudding user response:
It doest wait because even though handleLoadMore
is an async
function, inside the useEffect
there is no awaityng, the function just go to the end and loading changes from true
to false
almost instantly.
useEffect(() => {
// setLoading(true) - This setLoading is not necessary since true is the default.
handleLoadMore().then(() => {
setLoading(false)
})
}, []) // This only runs once, so the empty Array.
CodePudding user response:
You can make use either one of these:-
A. use your loading
state
- only display
data
ifloading=false
return (
<main className="flex flex-col md:max-w-3xl xl:max-w-6xl mx-auto text-gray-200 text-6xl ">
{!loading
? data.map(post => (
<Post
key={post.id}
image={post.image}
institution={post.institution}
title={post.title}
description={post.description}
createdAt={post.createdAt}
loved={post.loved}
author={post.author}
id={post.id}
/>
))
: 'Loading...'
}
<button
type="button"
className="px-4 py-3 bg-blue-400 rounded-full outline-none flex items-center
justify-center text-sm my-16 mx-auto w-4/12 hover:bg-blue-500
transition-colors duration-200 ease-out"
onClick={handleLoadMore}
>
Carregar Mais
</button>
</main>
);
B. set your data
state
initially to undefined
- currently you set them as
const [data, setData] = useState<PostProps[]>([])
- change it to
undefined
,const [data, setData] = useState<PostProps[]>()
. I'm not sure whether you can do it like this or not. I've never use thisuseState<Props>([])
syntax
before - then your current condition
data && data.map(post => (...
will work as intended. - It didn't work before cause
data
was set to be[]
/empty array initially.