Hydration error when using <Show>

Why <Show/> is giving me a hydration error here? i genuinely don't understand why. https://github.com/mrVinxyz/sldify/blob/tmp-docs/docs/src/components/api-reference.tsx
GitHub
sldify/docs/src/components/api-reference.tsx at tmp-docs · mrVinxyz...
SolidJS and TailwindCSS UI Library. Contribute to mrVinxyz/sldify development by creating an account on GitHub.
8 Replies
Adxtti
Adxtti4w ago
because <Show> renders its children based on the value of its when prop
if (!hasRequired() && prop.required) setHasRequired(true);
if (!hasDefault() && prop.default) setHasDefault(true);
if (!hasRequired() && prop.required) setHasRequired(true);
if (!hasDefault() && prop.default) setHasDefault(true);
This leads to a situation in which the server-rendered HTML doesn’t include ”Required” and ”Default” (since the signals are false) but the client-rendered HTML does therefore leading to your hydration error You should iterate over the props.components array to solve this
const hasRequired = props.components.some(component =>
component.props.some(prop => prop.required)
);
const hasDefault = props.components.some(component =>
component.props.some(prop => prop.default)
);
const hasRequired = props.components.some(component =>
component.props.some(prop => prop.required)
);
const hasDefault = props.components.some(component =>
component.props.some(prop => prop.default)
);
mrVinicius
mrViniciusOP4w ago
Thanks it solved the problem However i didn't fully understand why tho
This leads to a situation in which the server-rendered HTML doesn’t include ”Required” and ”Default” (since the signals are false) but the client-rendered HTML does therefore leading to your hydration error
This leads to a situation in which the server-rendered HTML doesn’t include ”Required” and ”Default” (since the signals are false) but the client-rendered HTML does therefore leading to your hydration error
Why the server doesn't include required/default but the client does? shouldn't they behave the same way? is there a difference with signals on the server vs the client?
Adxtti
Adxtti4w ago
https://docs.solidjs.com/guides/state-management https://docs.solidjs.com/reference/rendering/hydrate & https://www.solidjs.com/guides/server During server side rendering, hasRequired and hasDefault initialize at false — upon hydration, the client will run your logic setting the hasRequired and hasDefault signals to true, this mismatch is causing your hydration error I believe Solid behaves this way, and has its reasons, I'm sure a teams member will have a better response
mrVinicius
mrViniciusOP4w ago
<InputField
name='password'
label='Password'
leading={<LockIcon />}
placeholder='Enter password'
class={'!ps-8 !pe-16'}
/>

const Input: Component<InputProps> = (props) => {
const [local, rest] = splitProps(props, ['leading', 'trailing', 'class', 'variant', 'size']);

//const hasLeading = createMemo(() => local.leading); // this works
//const hasLeading = local.leading; // this works
return (
<div class={'relative'}>
{/* this throws a hydration error */}
<Show when={local.leading}>
{(leading) => (
<div class='absolute inset-y-0 left-0 flex items-center ps-1 pointer-events-none'>
{leading()}
</div>
)}
</Show>

{/* unrelated rest... */}
</div>
);
};
<InputField
name='password'
label='Password'
leading={<LockIcon />}
placeholder='Enter password'
class={'!ps-8 !pe-16'}
/>

const Input: Component<InputProps> = (props) => {
const [local, rest] = splitProps(props, ['leading', 'trailing', 'class', 'variant', 'size']);

//const hasLeading = createMemo(() => local.leading); // this works
//const hasLeading = local.leading; // this works
return (
<div class={'relative'}>
{/* this throws a hydration error */}
<Show when={local.leading}>
{(leading) => (
<div class='absolute inset-y-0 left-0 flex items-center ps-1 pointer-events-none'>
{leading()}
</div>
)}
</Show>

{/* unrelated rest... */}
</div>
);
};
this one left me even more confused, simply reassigning the variable const hasLeading = local.leading before passing into <Show/> solved the hydration issue hmm, i haven't read the old docs, and in the new there is not a mention of it. Found a quote in the old docs that kind of answers me: Similarly there is no reactivity on the server so do not update signals on initial render and expect them to reflect higher up the tree
mdynnl
mdynnl4w ago
tldr; if nodes are created and doesn't get rendered, you'll have hydration mismatch in server, reactivity system is static or more correctly, inert. signals do give you the latest values set to them but that's just it, anything else is one time executions except for a few cases like suspense. you're correct to assume that client/server execution shouldn't be different and it must be for the initial execution. during the hydration on the client after js kicks in, instead of creating DOM nodes like in SPA client rendering, solid tries to find them in current document to get references to them, where the document is a result of the html generated on the server with the code that was compiled to a series of string concatenations instead of DOM calls like in SPA mode. to also help with the finding and matching process, solid incrementally generates ids during rendering on server and client whenever strings are concatenated to generate html on the server or client to find the DOM nodes. on the client, if it can't find a DOM node using generated id, then we have a problem. solid used to silently create nodes but a change was made to throw instead so reduce edge cases. the solution to this is to prevent accidental node creations by resolving them only once and render them
mrVinicius
mrViniciusOP4w ago
yeah, my mistake was assuming reactivity worked on the server
mdynnl
mdynnl4w ago
does that clear anything up or did i just cause more confusion 🤣 but shorter and more simple case by code is
<div/>;
<div/>;
this simply will have hydration mismatch
mrVinicius
mrViniciusOP4w ago
yeah, it cleared up, im familiar with the hydration process, my issue really has with the reactivity
Want results from more Discord servers?
Add your server