Firstly, filename here is _runOnce.tsx. This file here is a client-side component that allows for important client side logic.
'use client'
export default function RunOnce() {
// access `window.localStorage` here.
// this is only available with 'use client'.
}
Secondly, the filename is app/layout.tsx. This is at the app root. This file by default is server-side. And it is advised not to make it client-side.
import RunOnce from './_runOnce'
export default function RootLayout({children}) {
return (
<body>
<RunOnce />
{children}
</body>
)
}
So, as you can see, the idea is to avoid making the layout.tsx client-side, because the issues that arise out of it is more painful.
Keeping the layout.tsx file strictly server-side and importing client-side components and plugging them in, keeps the app logic simple.
Why not write the run-only-once code in page.tsx instead?
Good question.
There's a reason not to.
That's why I'm writing this article.
The function Page() {} might and will contain useEffect code which cause the Page component to re-render.
Code that re-renders will never be able run a code ONLY once.
Can't we use useRef to not re-render the Page?
Nope. Not inside the Page function, because it'd just get instantiated every time with the re-render.
export function Page() {
const r = useRef(null) // useless.
...
}
To make the useRef route work, you'd need to pass the ref through maybe root layout, as an argument to the Page function.
And if you declare useRef() outside the Page function, then it's a rookie error, useRef is a client-side construct. Your code will never compile.
Conclusion
Hope it helps! Feel free to ask questions, if any.
Top comments (0)