S
SolidJS3mo ago
ensi

Hydration mismatch when trying to reference slot element outside of JSX

My component has two optional props leadingElement and trailingElement that expect a JSX element or fragment. I insert them like this:
{local.leadingElement}
// ...
{local.trailingElement}
{local.leadingElement}
// ...
{local.trailingElement}
When I try to reference these props outside of the JSX return, it results in a hydration mismatch:
// This line causes hydration mismatch.
const hasElementsOnAnySide = local.leadingElement || local.trailingElement;
// This line causes hydration mismatch.
const hasElementsOnAnySide = local.leadingElement || local.trailingElement;
Component works fine without this line. Code: https://pastebin.com/AjVSuhQM
Pastebin
import { createSignal, JSX, splitProps } from "solid-js";import { c...
Pastebin.com is the number one paste tool since 2002. Pastebin is a website where you can store text online for a set period of time.
15 Replies
ensi
ensiOP3mo ago
Component usage:
<Field
placeholder="Default Field"
leadingElement={
<div>just a div</div>
}
/>
<Field
placeholder="Default Field"
leadingElement={
<div>just a div</div>
}
/>
Madaxen86
Madaxen863mo ago
You should probably wrap the condition in the children wrapper https://docs.solidjs.com/reference/component-apis/children#children
mdynnl
mdynnl3mo ago
consider accepting components as opposed to elements if you’re okay with checking if they are passed or not
ensi
ensiOP3mo ago
I used it like this:
const hasElementsOnAnySide = children(() => local.leadingElement || local.trailingElement);
const hasElementsOnAnySide = children(() => local.leadingElement || local.trailingElement);
still the same error
mdynnl
mdynnl3mo ago
also, <local.leadingComponent /> is valid jsx
ensi
ensiOP3mo ago
according to my type:
type FieldProps = JSX.InputHTMLAttributes<HTMLInputElement> & {
class?: string;
leadingElement?: JSX.Element;
trailingElement?: JSX.Element;
};
type FieldProps = JSX.InputHTMLAttributes<HTMLInputElement> & {
class?: string;
leadingElement?: JSX.Element;
trailingElement?: JSX.Element;
};
I can't use this syntax because element is already constructed should I pass render function instead?
mdynnl
mdynnl3mo ago
yes, that’s what i meant in the last reply
ensi
ensiOP3mo ago
gonna try rn thanks, it worked! does it create overhead or it's fine?
mdynnl
mdynnl3mo ago
in general, it’s best to avoid working with elements and instead prefer components no overhead
ensi
ensiOP3mo ago
so it will compile to the same code?
mdynnl
mdynnl3mo ago
not the same code final output, but will get the same result given you don’t call the component twice
ensi
ensiOP3mo ago
can you explain this a little bit
jer3m01
jer3m013mo ago
Also
const hasElementsOnAnySide = local.leadingElement || local.trailingElement; // not reactive

// should be:
const hasElementsOnAnySide = () => local.leadingElement || local.trailingElement;
const hasElementsOnAnySide = local.leadingElement || local.trailingElement; // not reactive

// should be:
const hasElementsOnAnySide = () => local.leadingElement || local.trailingElement;
ensi
ensiOP3mo ago
this is a bit unintuitive, but I'm starting to understand thanks layout won't change so it shouldn't be reactive but I'm gonna add this as well
Want results from more Discord servers?
Add your server