Skip to content

Commit

Permalink
Best I was able to do
Browse files Browse the repository at this point in the history
  • Loading branch information
balegas committed Oct 3, 2024
1 parent 534fb08 commit 2d933e8
Show file tree
Hide file tree
Showing 6 changed files with 68 additions and 98 deletions.
44 changes: 26 additions & 18 deletions examples/nextjs-ssr-example/app/Home.tsx
Original file line number Diff line number Diff line change
@@ -1,22 +1,25 @@
"use client"

import { v4 as uuidv4 } from "uuid"
import { useShape, getShapeStream } from "@electric-sql/react"
import {
useShape,
getShapeStream,
SerializedShapeData,
} from "@electric-sql/react"
import "./Example.css"
import { matchStream } from "./match-stream"
import { Offset, ShapeData } from "@electric-sql/client/*"
import { Offset, ShapeStreamOptions } from "@electric-sql/client"
import { useEffect, useOptimistic, useState } from "react"
import { SSShape } from "./shape"

let offset: Offset | undefined
let shapeId: string | undefined = undefined
const shapePosition: { shapeId?: string; offset?: Offset } = {
shapeId: undefined,
offset: `-1`,
}

const itemShape = () => {
const baseItemShape: () => ShapeStreamOptions = () => {
if (typeof window !== `undefined`) {
return {
url: new URL(`/shape-proxy/items`, window?.location.origin).href,
offset,
shapeId,
}
} else {
const controller = new AbortController()
Expand All @@ -25,9 +28,16 @@ const itemShape = () => {
url: new URL(`https://not-sure-how-this-works.com/shape-proxy/items`)
.href,
signal: controller.signal,
subscribe: false,
}
}
}
const itemShape = () => ({ ...baseItemShape(), ...shapePosition })

const updateShapePosition = (offset: Offset, shapeId?: string) => {
shapePosition.offset = offset
shapePosition.shapeId = shapeId
}

type Item = { id: string }

Expand Down Expand Up @@ -67,22 +77,20 @@ async function clearItems() {
return await Promise.all([findUpdatePromise, fetchPromise])
}

export default function Home({ shape }: { shape: SSShape }) {
export default function Home({
shapes,
}: {
shapes: { items: SerializedShapeData }
}) {
const [isClient, setIsClient] = useState(false)
useEffect(() => setIsClient(true), [])

if (!offset) {
offset = shape.offset
shapeId = shape.shapeId ?? undefined
}

const shapeData = new Map(
Object.entries(shape?.data ?? new Map())
) as ShapeData
const { shapeId, offset, data } = shapes.items
updateShapePosition(offset, shapeId)

const { data: items } = useShape({
...itemShape(),
shapeData,
shapeData: new Map(Object.entries(data ?? new Map())),
}) as unknown as {
data: Item[]
}
Expand Down
3 changes: 2 additions & 1 deletion examples/nextjs-ssr-example/app/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import "./style.css"
import "./App.css"
import Image from "next/image"

export const metadata = {
title: `Next.js Forms Example`,
Expand All @@ -16,7 +17,7 @@ export default function RootLayout({
<body>
<div className="App">
<header className="App-header">
<img src="/logo.svg" className="App-logo" alt="logo" />
<Image src="/logo.svg" className="App-logo" alt="logo" />
{children}
</header>
</div>
Expand Down
20 changes: 18 additions & 2 deletions examples/nextjs-ssr-example/app/page.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,27 @@
import React from "react"
import { getShapeData } from "./shape"
import { getSerializedShape } from "@electric-sql/react"
import Home from "./Home"
import { unstable_noStore as noStore } from "next/cache"

// Hack to avoid caching behavior in Next.js
// should work just with {cache: `no-store`}
const fetchClient: typeof fetch = (...args) => {
const _url: URL =
args[0] instanceof URL ? args[0] : new URL(args[0] as string)
_url.searchParams.set(`_rand`, Math.random().toString())
args[0] = _url
return fetch(...args)
}

const itemShape = {
url: new URL(`http://localhost:3000/v1/shape/items`).href,
fetchClient,
}

const Page = async () => {
noStore()
return <Home shape={getShapeData()} />

return <Home shapes={{ items: getSerializedShape(itemShape) }} />
}

export default Page
77 changes: 0 additions & 77 deletions examples/nextjs-ssr-example/app/shape.tsx

This file was deleted.

18 changes: 18 additions & 0 deletions packages/react-hooks/src/react-hooks.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,17 @@ import {
ShapeStreamOptions,
Row,
ShapeData,
Offset,
} from '@electric-sql/client'
import React from 'react'
import { useSyncExternalStoreWithSelector } from 'use-sync-external-store/with-selector.js'

export type SerializedShapeData = {
offset: Offset
shapeId: string | undefined
data?: Record<string, unknown>
}

const streamCache = new Map<string, ShapeStream>()
const shapeCache = new Map<ShapeStream, Shape>()

Expand Down Expand Up @@ -140,3 +147,14 @@ export function useShape<

return useShapeData()
}
export function getSerializedShape(
options: ShapeStreamOptions
): SerializedShapeData {
const shapeStream = getShapeStream(options)
const shape = getShape(shapeStream)
return {
shapeId: shapeStream.shapeId,
offset: shapeStream.offset,
data: Object.fromEntries(shape.valueSync),
}
}
4 changes: 4 additions & 0 deletions packages/typescript-client/src/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,10 @@ export class ShapeStream<T extends Row = Row>
return this.#shapeId
}

get offset() {
return this.#lastOffset
}

get isUpToDate() {
return this.#isUpToDate
}
Expand Down

0 comments on commit 2d933e8

Please sign in to comment.