[SSR] Transitions may lead to missing elements after hydration
Describe the bug
Sometimes transitions may cause missing elements after hydration, especially if a component renders a signal that changes during the rendering process, like in the attached example. Commenting out startTransition wrapper in I18nProvider.tsx fixes the issue.
Your Example Website or App
https://stackblitz.com/edit/github-a26mtb?file=src/app.tsx,src/components/I18nProvider.tsx,src/components/Parent.tsx,src/components/Child.tsx
Steps to Reproduce the Bug or Issue
- Open the repro
- Pay your attention to Parent and Child components and what they're supposed to render.
- You can also refresh the page a few times to see that initially an expected output is rendered on the server but eventually Child component's content is vanished after hydration.
Expected behavior
A correct output from Parent & Child components.
Screenshots or Videos
Platform
System:
OS: macOS 14.5
CPU: (10) arm64 Apple M1 Pro
Memory: 157.41 MB / 16.00 GB
Shell: 5.9 - /bin/zsh
Binaries:
Node: 20.15.1 - ~/.nvm/versions/node/v20.15.1/bin/node
Yarn: 1.22.22 - ~/.nvm/versions/node/v20.15.1/bin/yarn
npm: 10.7.0 - ~/.nvm/versions/node/v20.15.1/bin/npm
Browsers:
Chrome: 129.0.6668.103
Safari: 17.5
Additional context
The issue is only reproducible when using SSR.
It's worth mentioning that I just stumbled upon another yet similar bug (setup is similar to one in a repro but now I'm using https://github.com/solidjs-community/solid-primitives/tree/main/packages/i18n) where changing a locale during rendering may cause unstable output - sometimes t returns en translation even though a language was explicitly set to fr in the parent component, and sometimes it returns the right translation accounting fr language.
I still haven't managed to get a minimal reproducible example (without a library) and I have some doubts this issue is directly related to Solid but going to leave it here just for additional info that may help.
https://github.com/user-attachments/assets/5f2d995d-344e-4282-adec-ead7257fde2c
You can do this as follows:
import type { JSX } from 'solid-js';
import { useI18n } from '~/primitives/i18n';
export default function Parent(props: { children?: JSX.Element }) {
const { locale, changeLocale } = useI18n();
changeLocale('fr');
return (
<div> // NOTE: wrapper required - Fragment breaks SolidJS reactivity with immediate locale change
{locale()}
{props.children}
</div>
);
}
Fragments are designed not to create DOM nodes - this is their fundamental characteristic. I think these types of issues are best addressed through framework or browser constraint awareness rather than adding complexity to the library.
If this is a common issue, it should be fixed, but it's hard to tell at this point. We'll need to hear from the maintainers.