Enabling cache components leads to errors with some base ui components.
Unanswered
Spectacled bear posted this in #help-forum
Spectacled bearOP
Just upgraded to next 16 and tried enabling cache components in the config, but it leads to errors with some ui components from base ui. Specifically, I get an error with the tabs component.
The error is due to
So it wants me to wrap the component in a Suspense.
I don't understand why I only get this error when cache components is enabled.
The error is due to
Math.random() being used internally by the component. The error message says I can't use that within a client component without fallback ui. So it wants me to wrap the component in a Suspense.
I don't understand why I only get this error when cache components is enabled.
63 Replies
@Spectacled bear Just upgraded to next 16 and tried enabling cache components in the config, but it leads to errors with some ui components from base ui. Specifically, I get an error with the tabs component.
The error is due to `Math.random()` being used internally by the component. The error message says I can't use that within a client component without fallback ui.
So it wants me to wrap the component in a Suspense.
I don't understand why I only get this error when cache components is enabled.
How did you use Math.random() in the client component? did you use it in hooks that would get prerendered in the server?
@alfonsüs ardani How did you use Math.random() in the client component? did you use it in hooks that would get prerendered in the server?
Spectacled bearOP
Have a client component file that imports the base ui tab component. I'm guessing the base ui component uses it internally. I didn't explicitly use Math.random() within my components.
The base ui tab indicator subcomponent gets flagged as using Math.random().
Don't get this error when cache components is disabled.
The base ui tab indicator subcomponent gets flagged as using Math.random().
Don't get this error when cache components is disabled.
Interesting.
This is somewhat already a feature in the canary/beta space
They detects any uses of Math.random in pre-rendered client components as a way to tell the developers to avoid any rendering mis-match. As you know, next.js will try to pre-render client components as much as possible (until it can't) and the result will be hydrated again in the client which will make rendering happens twice
if you add Math.random it will produce mis-match between the server-pre-render phase and client-re-hydrating phase which will gives you the "Hydration" error just like usual
But now in v16, next goes an extra mile to "wrap" that error and give you a more informative error message to help developers avoid using math.random on pre-rendered client componnets
one way to avoid this is to avoid the pre-rendering phase of client component such as using the mounted state
export function NoSSRClientComponent(){
const [mounted, setMounted] = useState(false)
useEffect(() => setMounted(true), [])
if (!mounted) return null
// at server will return this, resulting in blank initial state
return <>{children}</>
// at client browser will hydrate this.
}or just, wrap the thing with <Suspense>
Spectacled bearOP
Yeah I understand that but there are some things that don't add up. So this error only occurs with this base ui tabs component when cache components is enabled .
There is no error even on next 16 when cache components is disabled.
but weird thing is that if I try to explicitly use
So nextjs is flagging base ui tabs indicator subcomponent as using
But if explicitly use
There is no error even on next 16 when cache components is disabled.
but weird thing is that if I try to explicitly use
Math.random() on a client component, I get the error regardless if cache components are disabled or not. So nextjs is flagging base ui tabs indicator subcomponent as using
Math.random() but only gives the error when cache component is enabled. But if explicitly use
Math.random() in a client component, I will get the error when cache components is enabled and disabled.interesting
yeah i have no idea why base ui does that 

Spectacled bearOP
I looked through the source files for the tab component and figured out the cause. Base ui uses
It seems that when cache components is disabled, Next only gives the error when
When cache components is enabled, Next gives an error regardless if
Math.random() internally within a useState() hook. It seems that when cache components is disabled, Next only gives the error when
Math.random() is used outside of a useState(). When cache components is enabled, Next gives an error regardless if
Math.random() is used within a useState() hook or not.Pacific sand lance
it actually makes sense if you think about it
either you have to cache component (then Math.random() is cached) or use
await connection() to ensure it's computed during requestalso, if you want to use it in client component, you have to do that in useEffect or ensure it won't be ssr'ed
yeah but this is a Tab component which is weird to have it as CSR by default. What if i want to make tab based on searchparams?
one would assume base-ui is creating base component for wide variety of use cases...
Pacific sand lance
for search params i'm using nuqs which provides loaders/parsers both for server and for client
@alfonsüs ardani one would assume base-ui is creating base component for wide variety of use cases...
Pacific sand lance
cuz they are
yes but Tab would still give that Math.random error
Pacific sand lance
it's related to nextjs, not base-ui
why would i need to put my Tab to be exclusively not rendered in the server?
Pacific sand lance
it can be rendered server side
putting Tab out of SSR would hurt SEO and etc etc
Pacific sand lance
just adjust ur code
it can but it would throw that Math.random error
Pacific sand lance
had similiar issues after i opted-in (i used shadcn and next15 canary release)
just moved math random from useMemo to useEffect + setWidth
yes but you can't move the math random...
Pacific sand lance
in my case it was fine since it was sidebar menu skeleton so it didnt flicker at all
math random is inside the source code of base-ui tabs component...
Pacific sand lance
then you can reach base-ui maintainers
nothing else ig
yea now we are on the same page 

Pacific sand lance
wonder why they use Math.random in tabs tho
i can only guess one reason its to make automatic id generation so you dont have to pass in values to the TabItem or TabContent and just infer based on the order (since its stable list anyway)
in which at that point you should've used
useId() instead of Math.randomPacific sand lance
they probably use React.useId()
otherwise you would get hydration errors
@Pacific sand lance they probably use React.useId()
Spectacled bearOP
They should use
useId I think but currently they are using math.random.let counter = 0;
export function generateId(prefix: string) {
counter += 1;
return `${prefix}-${Math.random().toString(36).slice(2, 6)}-${counter}`;
}Pacific sand lance
so theyre mixing the two... (?)
Pacific sand lance
they use useId with prefix (if provided)
it has nothing to do with math random, must be something else
I was able to contact one of their devs. They are looking into it.
Spectacled bearOP
The base ui devs are super quick to respond to issues.
They have pushed prs for a couple of my issues within a couple hours.
awesome, glad to hear that
Pacific sand lance
duh
this generateId is for some instance id
whgatever it is
I suppose theyre working on it
Maybe u can pull up a quick PR 👀

