Skip to content

Commit

Permalink
Order items to prevent hydration issues
Browse files Browse the repository at this point in the history
  • Loading branch information
balegas committed Oct 3, 2024
1 parent 4a48ea6 commit 02ffd0d
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 20 deletions.
38 changes: 19 additions & 19 deletions examples/nextjs-ssr-example/app/Home.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,11 @@ import {
import "./Example.css"
import { matchStream } from "./match-stream"
import { Offset, ShapeStreamOptions } from "@electric-sql/client"
import { useEffect, useOptimistic, useState } from "react"
import { useOptimistic } from "react"

const parser = {
timestamptz: (date: string) => new Date(date).getTime(),
}

const shapePosition: { shapeId?: string; offset?: Offset } = {
shapeId: undefined,
Expand Down Expand Up @@ -39,7 +43,7 @@ const updateShapePosition = (offset: Offset, shapeId?: string) => {
shapePosition.shapeId = shapeId
}

type Item = { id: string }
type Item = { id: string; created_at: number }

async function createItem(newId: string) {
const itemsStream = getShapeStream(itemShape())
Expand Down Expand Up @@ -82,15 +86,13 @@ export default function Home({
}: {
shapes: { items: SerializedShapeData }
}) {
const [isClient, setIsClient] = useState(false)
useEffect(() => setIsClient(true), [])

const { shapeId, offset, data } = shapes.items
updateShapePosition(offset, shapeId)

const { data: items } = useShape({
...itemShape(),
shapeData: new Map(Object.entries(data ?? new Map())),
parser,
}) as unknown as {
data: Item[]
}
Expand All @@ -108,21 +110,17 @@ export default function Home({
// possible duplicates as there's a potential race condition where
// useShape updates from the stream slightly before the action has finished.
const itemsMap = new Map()
state.concat([{ id: newId }]).forEach((item) => {
itemsMap.set(item.id, { ...itemsMap.get(item.id), ...item })
})
state
.concat([{ id: newId, created_at: new Date().getTime() }])
.forEach((item) => {
itemsMap.set(item.id, { ...itemsMap.get(item.id), ...item })
})
return Array.from(itemsMap.values())
}

return []
})

// Can't render entries on the server because order of
// items is not guaranteed after de/serialization.
if (!isClient) {
return null
}

return (
<div>
<form
Expand All @@ -146,11 +144,13 @@ export default function Home({
Clear
</button>
</form>
{optimisticItems.map((item: Item, index: number) => (
<p key={index} className="item">
<code>{item.id}</code>
</p>
))}
{optimisticItems
.sort((a, b) => a.created_at - b.created_at)
.map((item: Item, index: number) => (
<p key={index} className="item">
<code>{item.id}</code>
</p>
))}
</div>
)
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
-- Create a simple items table.
CREATE TABLE IF NOT EXISTS items (
id TEXT PRIMARY KEY NOT NULL
id TEXT PRIMARY KEY NOT NULL,
created_at TIMESTAMPTZ DEFAULT NOW() NOT NULL
);

-- Populate the table with 10 items.
Expand Down

0 comments on commit 02ffd0d

Please sign in to comment.