在SolidStart/SolidJS中使用splitProps遭遇Hydration mismatch错误
Hydration Mismatch 问题分析与解决
问题描述
你的Button组件在SSR/SSG场景下触发了Hydration mismatch错误,错误提示为:
Hydration Mismatch. Unable to find DOM nodes for hydration key: 00000000100...
错误指向组件的子元素,且你发现将children从specialProps移至passedProps后,问题即可解决,但不清楚背后原因。
复现代码:
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> ); }
原因分析
核心问题在于服务端与客户端对children的渲染路径不一致:
- 在SSR/SSG过程中,React会为每个DOM节点生成唯一的
hydration key,用于客户端Hydration时匹配服务端输出的DOM结构。 - 当你将
children拆分到specialProps并在组件内部显式渲染{specialProps.children}时,相当于在Button组件层级对children做了一次“手动转发”。这会改变React在服务端生成的hydration标记逻辑——服务端原本会将children作为Button组件的直接子节点处理,但客户端渲染时,children是从specialProps中取出后渲染,两者的DOM节点追踪路径出现差异,导致hydration key不匹配,触发错误。 - 而将
children移至passedProps后,children会通过{...passedProps}直接传递给<button>标签,这完全符合React默认处理子元素的逻辑:服务端和客户端对children的渲染路径完全一致,hydration key自然匹配,错误也就消失了。
解决方案
保持children的渲染逻辑与React默认行为一致,将children从splitProps的第一组参数中移除,让其随passedProps传递给<button>标签:
export function Button(props) { const [specialProps, passedProps] = splitProps(props, [ "class", "disabled", "leftIcon", ]); const buttonCva = cva("btn", { variants: { disabled: { true: "btn-disabled", }, }, }); return ( <button class={buttonCva(specialProps)} {...passedProps}> {specialProps.leftIcon} </button> ); }
此时children会自动通过passedProps传递给<button>,无需显式渲染。
内容的提问来源于stack exchange,提问作者Gabriel Cséfalvay
相关产品推荐
相关产品推荐

