S
SolidJS•5mo ago
AlberTenez

Unexpected behaviour on a shuffled hardcoded list with Solid Start

I'm currently experiencing a fascinating issue. Given the code:
import { type JSXElement, For, createSignal } from 'solid-js';

export function shuffle<T extends unknown[]>(array: T): T {
let currentIndex = array.length,
randomIndex;

// While there remain elements to shuffle.
while (currentIndex > 0) {
// Pick a remaining element.
randomIndex = Math.floor(Math.random() * currentIndex);
currentIndex--;

// And swap it with the current element.
[array[currentIndex], array[randomIndex]] = [array[randomIndex], array[currentIndex]];
}

return array;
}

export default function BeautifulPlaces(): JSXElement {
const [places] = createSignal(
shuffle([
{
name: 'Chengdu',
image: '/images/chengdu.webp',
},
{
name: 'Beijin',
image: '/images/beijin.webp',
},
{
name: 'Bamboo Forest',
image: '/images/bamboo-forest.webp',
},
{
name: 'Datong',
image: '/images/datong.webp',
},
]),
);

return (
<div class="w-full overflow-x-auto xl:container mx-auto">
<For each={places()}>
{(place) => (
<div
style={{ 'background-image': `url('${place.image}')` }}
class="min-w-[200px] h-64 flex items-end justify-center text-center text-text-light font-bold text-lg rounded-xl bg-cover bg-center"
>
<span class="block w-full bg-background-dark bg-opacity-70 rounded-b-xl">
{place.name}
</span>
</div>
)}
</For>
</div>
);
import { type JSXElement, For, createSignal } from 'solid-js';

export function shuffle<T extends unknown[]>(array: T): T {
let currentIndex = array.length,
randomIndex;

// While there remain elements to shuffle.
while (currentIndex > 0) {
// Pick a remaining element.
randomIndex = Math.floor(Math.random() * currentIndex);
currentIndex--;

// And swap it with the current element.
[array[currentIndex], array[randomIndex]] = [array[randomIndex], array[currentIndex]];
}

return array;
}

export default function BeautifulPlaces(): JSXElement {
const [places] = createSignal(
shuffle([
{
name: 'Chengdu',
image: '/images/chengdu.webp',
},
{
name: 'Beijin',
image: '/images/beijin.webp',
},
{
name: 'Bamboo Forest',
image: '/images/bamboo-forest.webp',
},
{
name: 'Datong',
image: '/images/datong.webp',
},
]),
);

return (
<div class="w-full overflow-x-auto xl:container mx-auto">
<For each={places()}>
{(place) => (
<div
style={{ 'background-image': `url('${place.image}')` }}
class="min-w-[200px] h-64 flex items-end justify-center text-center text-text-light font-bold text-lg rounded-xl bg-cover bg-center"
>
<span class="block w-full bg-background-dark bg-opacity-70 rounded-b-xl">
{place.name}
</span>
</div>
)}
</For>
</div>
);
When SSR is rendering the place.image + the place.name match. But when hydration on the client happens then the image and the name does not render correctly, seems like is updating the image but not the name, and I can't figure out why this is happening.
7 Replies
AlberTenez
AlberTenez•5mo ago
I also tried to add the shuffle inside a createEffect and update places with a setPlaces Setter. But not success. You can see the image missmatch happening on https://viatsy.com/ (site under construction)
Viatsy - Travel made easy
All you business needs in one app
bigmistqke
bigmistqke•5mo ago
I guess the ssr'd output and the client's output will be different with your current implementation, causing hydration issues. maybe try createResource instead. I think with createResource the output/promises are serialized.
You can see the image missmatch happening on https://viatsy.com/ (site under construction)
i looked at the site but couldn't notice anything peculiar as i don't know how the images are supposed to look like.
AlberTenez
AlberTenez•5mo ago
Ey @bigmistqke , thanks for your reply. In regards of the page, you can inspect the html, the images are named as the placeholder 🙂 Let me try createResource. I can confirm that createResource does the job Why does it work, though? So it generates the resource on the server and does not regenerate in client as it gets serialised from server?
bigmistqke
bigmistqke•5mo ago
So it generates the resource on the server and does not regenerate in client as it gets serialised from server?
exactly before you were creating two different states, because it's randomised, causing hydration mismatches. kind of surprising it didn't error too.
bigmistqke
bigmistqke•5mo ago
https://www.youtube.com/watch?v=oQ1zn7cdtyU is a nice presentation on suspense/resource if u wanna know mor
AlberTenez
AlberTenez•5mo ago
Roger that! Thank you so much I'll watch the presentation tonight! 💪 Thanks 🙂
bigmistqke
bigmistqke•5mo ago
ur welcome!