I’m working on a T3 app using TS, React, Next.js, prisma and tRPC. I have a header in my app showing the number of credits a user has. To get the number of credits I make a call to an API which takes some time to return an answer. As I use the amount of credits as a state, this means that the page renders with credits undefined before the API returns e.g. 10.
The concept of it looks like this:
import { useEffect, useState } from 'react'
import { api } from '~/utils/api'
export function Header() {
const nbrOfCredits = api.user.getCredits.useQuery()
const [credits, setCredits] = useState(nbrOfCredits.data)
return <>Credits remaining: {credits}</>
}
Credits is recognized as number | undefined.
My API is working fine, it just takes too long for the response for the state to be set.
I’ve tried a lot of stuff but I’m very new to webdev and not exactly an expert in either React, TS or JS.
I figured setting the value again in a useEffect on render might do the trick but it is still undefined. Once the page is loaded I can console log a value of nbrOfCredits so it does eventually show up.
I also tried creating a function to call on render using try, catch, finally but I never got that to work either:
async function handleCreditsRefresh() {
try {
setIsLoading(true)
await nbrOfCredits
.refetch()
.then(() => {
const cred =
typeof nbrOfCredits === 'undefined' ? 0 : nbrOfCredits.data
setCredits(cred)
})
.catch((err) => {
setError(err)
})
.finally(() => setIsLoading(false))
} catch (error) {
console.log(error)
}
}
useEffect(() => {
void handleCreditsRefresh()
}, [])
return (
<>
{isLoading ? (
<>Credits remaining: </>
) : (
<>Credits remaining: {credits}</>
)}
</>
)
2
Answers
I solved it in a good enough way I think with the input from knoxgon.
and in the return:
using nbrOfCredits.data, the engine waits for the API response before rendering the component, basically solving my problem. I have a button for refreshing the credits though so I need to keep the logic in handleCreditsRefresh.
I see that you’re using
useQuery
which normally provides access toisLoading
anddata
which you can leverage.What you need to do is wait for the request to be completed. You would use conditional rendering to ensure that data is only rendered when it’s available.