I'm getting a hydration mismatch error for this code, and I don't really understand why.
Hydration Mismatch. Unable to find DOM nodes for hydration key: 00000000100...
and indicating the child of this component
Here is a minimal code sample:
export function Button(props) {
const [specialProps, passedProps] = splitProps(props, [
"class",
"children",
"disabled",
"leftIcon",
]);
const buttonCva = cva("btn", {
variants: {
disabled: {
true: "btn-disabled",
},
},
});
return (
<button class={buttonCva(specialProps)} {...passedProps}>
{specialProps.leftIcon}
{specialProps.children}
</button>
);
}
What I figured out so far is that if I remove from "children"
specialProps
(so it will be in passedProps
), it works.
I'm getting a hydration mismatch error for this code, and I don't really understand why.
Hydration Mismatch. Unable to find DOM nodes for hydration key: 00000000100...
and indicating the child of this component
Here is a minimal code sample:
export function Button(props) {
const [specialProps, passedProps] = splitProps(props, [
"class",
"children",
"disabled",
"leftIcon",
]);
const buttonCva = cva("btn", {
variants: {
disabled: {
true: "btn-disabled",
},
},
});
return (
<button class={buttonCva(specialProps)} {...passedProps}>
{specialProps.leftIcon}
{specialProps.children}
</button>
);
}
What I figured out so far is that if I remove from "children"
specialProps
(so it will be in passedProps
), it works.
1 Answer
Reset to default 0So I figured out what is the problem: Any elements that are generated during render, are then searched for in the DOM during hydration. In the code above, the children were rendered twice, because
- first, the
buttonCva()
function evaluated them (probably reading the whole specialProps object), and then, - for the second time,
{specialProps.children}
evaluated them.
No. 2 got inserted into the DOM, but no. 1 just got discarded - so the hydration script on the client side couldn't find it anywhere in the DOM.
So here is the corrected code:
export function Button(props) {
const [classProps, childrenProps, passedProps] = splitProps(props, [
"class",
"disabled",
],[
"children",
"leftIcon",
]);
const buttonCva = cva("btn", {
variants: {
disabled: {
true: "btn-disabled",
},
},
});
return (
<button class={buttonCva(classProps)} {...passedProps}>
{childrenProps.leftIcon}
{childrenProps.children}
</button>
);
}
In hindsight, it's a silly mistake. But the hydration process and requirements of SolidStart is not that well documented so far.
Here is some reading that helped me:
Hydration error for rendered Elements that aren't inserted in the DOM during server rendering
#1977
<Show when={JSX.Element} /> breaks SSR (causes Hydration Errors) #2345