here is the code:
import { type AppType } from 'next/app'
import { api } from '~/utils/api'
import '~/styles/globals.css'
import Nav from '~/components/Nav'
import { useEffect, useState } from 'react'
const MyApp: AppType = ({ Component, pageProps }) => {
const [showCart, setShowCart] = useState(false)
const [loading, setLoading] = useState(false)
const createSession = api.user.createSession.useMutation()
const generateId = async (): Promise<string | undefined> => {
const res = await createSession.mutateAsync()
if (res.response) {
return res.response.id
} else if (res.error) {
return res.error
}
}
const setSessionId = async () => {
const tmp: string | undefined = await generateId()
if (tmp) document.cookie = `sessionId=${tmp}`
setLoading(false)
}
useEffect(() => {
if (!loading) {
setLoading(true)
const cookieString: string = document.cookie
const cookies: string[] = cookieString.split(';') || []
let sessionId: string | null = null
for (let i = 0; i < cookies.length; i++) {
const cookie: string | undefined = cookies[i]
if (!cookie || cookie.trim() === '') {
continue
}
if (cookie.trim().startsWith('sessionId=')) {
sessionId = cookie.trim().substring('sessionId='.length)
break
}
}
if (!sessionId) {
void setSessionId()
}
}
}, [])
return (
<>
<Nav showCart={showCart} setShowCart={setShowCart} />
<h1>{loading && 'LOADING'}</h1>
<Component {...pageProps} />
</>
)
}
export default api.withTRPC(MyApp)
I am using trpc and prisma. for some reason the useEffect is running twice and it is posting to the db twice. any idea what’s causing the re-render? the loading is always false for some reason even after I set it to true. is it because I am setting it wrong?
I initially thought that maybe it was rendering twice, once in the server and once in the client. but I logged the window object and they were both defined.
any idea what I am doing wrong?
2
Answers
I think this wokr once setLoadin to true , and update useEffect
The issue you’re experiencing with useEffect running twice and posting to the database twice could be related to the Next.js server-side rendering (SSR) behavior. When using Next.js, the initial rendering occurs on the server and then the component rehydrates on the client side.
To address this, you can add a condition in your useEffect to only execute the code on the client side. You can do this by checking if typeof window is defined, as the window object is only available in the browser environment.
Here’s an updated version of your code with the modification:
By adding typeof window !== ‘undefined’ as a condition, the code inside the useEffect will only run on the client side and prevent it from executing on the server side during the initial render. This should help eliminate the duplicated database posts.
Regarding the issue with loading always being false, it could be because setLoading(true) is asynchronous, and the subsequent line if (!loading) may not reflect the updated value immediately. If you need to check the value of loading, you can add a console.log statement after setLoading(true) to see if it changes accordingly.
Make sure to test your code with this modification and verify if the behavior is as expected.