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
dataifloading=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>([])syntaxbefore - then your current condition
data && data.map(post => (...will work as intended. - It didn't work before cause
datawas set to be[]/empty array initially.
