How can I make a client component (which needs to be server rendered) later unmount itself
Unanswered
୧ʕ•̀ᴥ•́ʔ୨ posted this in #help-forum
I have this overlay component which, only in the browser, and under a certain condition needs to unmount itself. But the code below doesn't work:
I can't use a dynamic import because it causes a flash of content before the message appears when the value isn't in local storage. What would be a good solution to this?
'use client'
export default function Overlay() {
const inBrowser = typeof window !== 'undefined'
const hasSpecialValue = inBrowser && localStorage.getItem('special-value')
if (hasSpecialValue) {
return null
}
return <p>This message needs to be server rendered and only removed on the client if special value is found in local storage.</p>
}I can't use a dynamic import because it causes a flash of content before the message appears when the value isn't in local storage. What would be a good solution to this?
29 Replies
@୧ʕ•̀ᴥ•́ʔ୨ I have this overlay component which, only in the browser, and under a certain condition needs to unmount itself. But the code below doesn't work:
js
'use client'
export default function Overlay() {
const inBrowser = typeof window !== 'undefined'
const hasSpecialValue = inBrowser && localStorage.getItem('special-value')
if (hasSpecialValue) {
return null
}
return <p>This message needs to be server rendered and only removed on the client if special value is found in local storage.</p>
}
I can't use a dynamic import because it causes a flash of content before the message appears when the value isn't in local storage. What would be a good solution to this?
Can you clarify what you want to archive? That might help: https://xyproblem.info/
I have an overlay that appears over the page by default, unless you're a special type of user and in your local storage you have this value, in which case the overlay needs to disappear. The important thing is that flash of the page isn't acceptable for normal users (who will see the overlay appear), whereas flash of the message which then disappears is acceptable for the "special" users
Or ideally there wouldn't be a flash at all, but it's only a requirement that normal users don't see one
@୧ʕ•̀ᴥ•́ʔ୨ Or ideally there wouldn't be a flash at all, but it's only a requirement that normal users don't see one
So if I understand you right, you want to have a overlay if a user is allowed to see this overlay (if value is in localstorage) and if not, the user should see the overlay. There should be no flash
Correct?
It's the opposite, overlay is there by default for everyone, but will disappear (with a delay/flash is fine) if you happen to have the value in localstorage
@୧ʕ•̀ᴥ•́ʔ୨ It's the opposite, overlay is there by default for everyone, but will disappear (with a delay/flash is fine) if you happen to have the value in localstorage
thanks for clarification. And the content itself is rendered serverside, right?
Yes, correct
Well, that’s a problem. Because the overlay should be directly visible. But it won’t, because the client need to load it first. And that happens only after the server side content has rendered. So add it to your serverside content so it will be showed instantly and will then be either hidden or not
Uh sure, but how do I hide it later?
@୧ʕ•̀ᴥ•́ʔ୨ Uh sure, but how do I hide it later?
The client component „Overlay“ (or however you called it) will be rendered and that component checks the condition, that you need and hides itself when the condition is met or it stays visible
I tried that (see the code example at the start), but apparently you can't return different values on the client than on the server.
So I can't check the condition and return null or false from the component on the client
Ideally I'd want the component to unmount itself as it's not needed
@୧ʕ•̀ᴥ•́ʔ୨ I tried that (see the code example at the start), but apparently you can't return different values on the client than on the server.
The client component can still conditionally render. So if the condition is met, return null and if not display the overlay (if not is the default)
You mean in the parent? The parent is a server component, so it can't access local storage
This code doesn't work though
The overlay doesn't disappear on the client
If I try to return anything different I get a hydration error, if I return null or false, it simply does nothing (it stays as it is)
@୧ʕ•̀ᴥ•́ʔ୨ This code doesn't work though
The code works perfectly: https://codesandbox.io/p/devbox/pedantic-sid-2hn53t
Thanks for setting that up. I wanted to avoid the flash of content on page load, the overlay should be there by default, this is why I was avoiding using dynamic()
@୧ʕ•̀ᴥ•́ʔ୨ Thanks for setting that up. I wanted to avoid the flash of content on page load, the overlay should be there by default, this is why I was avoiding using dynamic()
the overlay is instantly there. It will appear directly with the serverside rendered content
Is the flash only in dev mode then? When I press refresh on the codesandbox, I see the buttons first, and then the overlay appears and pushes them down
Well the overlay is meant to cover the content of the page, so I don't want there to be a flash of the page before the overlay appears
When I build it locally and run it with npm run start, there's a bit of a flash of the underlying content before the overlay shows up
@୧ʕ•̀ᴥ•́ʔ୨ I have this overlay component which, only in the browser, and under a certain condition needs to unmount itself. But the code below doesn't work:
js
'use client'
export default function Overlay() {
const inBrowser = typeof window !== 'undefined'
const hasSpecialValue = inBrowser && localStorage.getItem('special-value')
if (hasSpecialValue) {
return null
}
return <p>This message needs to be server rendered and only removed on the client if special value is found in local storage.</p>
}
I can't use a dynamic import because it causes a flash of content before the message appears when the value isn't in local storage. What would be a good solution to this?
im busy right now so cant come up with an example for you yet, but check how nextra does it with the banner: https://github.com/shuding/nextra/blob/main/packages/nextra-theme-docs/src/components/banner.tsx
in particular lines 12-14.
basically:
* you use a script to check localStorage before hydration, if it says to remove the overlay, add a class to the html or the body element
* use css to hide the overlay whenever the class is present
*
in particular lines 12-14.
basically:
* you use a script to check localStorage before hydration, if it says to remove the overlay, add a class to the html or the body element
* use css to hide the overlay whenever the class is present
*
suppressHydrationWarning in the html/body element you chose in step 1Thanks, that's a useful pointer, I'll take a look