Skip to content

Commit

Permalink
test use cache stuff
Browse files Browse the repository at this point in the history
  • Loading branch information
stipsan committed Nov 21, 2024
1 parent f22bc1a commit 3cc0870
Show file tree
Hide file tree
Showing 9 changed files with 167 additions and 87 deletions.
1 change: 1 addition & 0 deletions next-canary/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"scripts": {
"build": "next build",
"dev": "next dev --turbopack",
"typegen:generate": "sanity typegen generate",
"lint": "next lint",
"start": "next start"
},
Expand Down
3 changes: 3 additions & 0 deletions next-canary/sanity-typegen.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"schema": "../studio/schema.json"
}
48 changes: 48 additions & 0 deletions next-canary/src/app/SanityLive.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
'use client'

import {client} from '@/sanity/client'
import type {LiveEventMessage, LiveEventRestart, LiveEventWelcome} from '@sanity/client'
import {CorsOriginError} from '@sanity/client'
import {useRouter} from 'next/navigation'
import {useEffect} from 'react'
import {useEffectEvent} from 'use-effect-event'
import {expireTags} from './actions'

export function SanityLive() {
const router = useRouter()

const handleLiveEvent = useEffectEvent(
(event: LiveEventMessage | LiveEventRestart | LiveEventWelcome) => {
if (event.type === 'welcome') {
console.info('Sanity is live with automatic invalidation of published content')
} else if (event.type === 'message') {
expireTags(event.tags).then(() => router.refresh())
} else if (event.type === 'restart') {
router.refresh()
}
},
)
useEffect(() => {
const subscription = client.live.events().subscribe({
next: (event) => {
if (event.type === 'message' || event.type === 'restart' || event.type === 'welcome') {
handleLiveEvent(event)
}
},
error: (error: unknown) => {
if (error instanceof CorsOriginError) {
console.warn(
`Sanity Live is unable to connect to the Sanity API as the current origin - ${window.origin} - is not in the list of allowed CORS origins for this Sanity Project.`,
error.addOriginUrl && `Add it here:`,
error.addOriginUrl?.toString(),
)
} else {
console.error(error)
}
},
})
return () => subscription.unsubscribe()
}, [])

return null
}
22 changes: 22 additions & 0 deletions next-canary/src/app/ThemeButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
'use client'

import type {SyncTag} from '@sanity/client'
import {useTransition} from 'react'
import {randomColorTheme} from './actions'

export function ThemeButton({tags}: {tags: SyncTag[]}) {
const [pending, startTransition] = useTransition()
return (
<button
disabled={pending}
onClick={() =>
startTransition(async () => {
await randomColorTheme(tags)
})
}
className={`bg-theme-button text-theme-button focus:ring-theme focus:ring-offset-theme rounded-md px-4 py-2 text-sm font-semibold transition ease-in-out focus:outline-none focus:ring-2 focus:ring-opacity-50 focus:ring-offset-2 focus:duration-0 disabled:cursor-not-allowed disabled:opacity-50 ${pending ? 'animate-pulse cursor-wait duration-150' : 'duration-1000'} `}
>
{pending ? 'Generating...' : 'Random Color Theme'}
</button>
)
}
17 changes: 17 additions & 0 deletions next-canary/src/app/actions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
'use server'

import type {SyncTag} from '@sanity/client'
import {expireTag} from 'next/cache'

export async function expireTags(tags: SyncTag[]) {
expireTag(...tags)
console.log(`<SanityLive /> expired tags: ${tags.join(', ')}`)
}

export async function randomColorTheme(tags: SyncTag[]) {
const res = await fetch('https://lcapi-examples-api.sanity.dev/api/random-color-theme', {
method: 'PUT',
})
expireTag(...tags)
return res.json()
}
37 changes: 29 additions & 8 deletions next-canary/src/app/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,41 @@
import type {Metadata} from 'next'
import type {Viewport} from 'next'
import './globals.css'
import {sanityFetch} from '@/sanity/fetch'
import {defineQuery} from 'groq'
import {SanityLive} from './SanityLive'
import {ThemeButton} from './ThemeButton'

export const metadata: Metadata = {
title: 'Create Next App',
description: 'Generated by create next app',
const THEME_QUERY = defineQuery(`*[_id == "theme"][0]{background,text}`)

export async function generateViewport(): Promise<Viewport> {
const {data} = await sanityFetch({query: THEME_QUERY})
return {
themeColor: data?.background,
}
}

export default function RootLayout({
export default async function RootLayout({
children,
}: Readonly<{
children: React.ReactNode
}>) {
const {data, tags} = await sanityFetch({query: THEME_QUERY})

return (
<html lang="en">
<body className="bg-theme text-theme transition-colors duration-1000 ease-in-out">
{children}
<html
lang="en"
className="bg-theme text-theme transition-colors duration-1000 ease-in-out"
style={{
['--theme-background' as string]: data?.background,
['--theme-text' as string]: data?.text,
}}
>
<body>
<div className="flex min-h-screen flex-col items-center justify-evenly overflow-auto">
{children}
<ThemeButton tags={tags!} />
</div>
<SanityLive />
</body>
</html>
)
Expand Down
99 changes: 20 additions & 79 deletions next-canary/src/app/page.tsx
Original file line number Diff line number Diff line change
@@ -1,83 +1,24 @@
import Image from 'next/image'
import {sanityFetch} from '@/sanity/fetch'
import './globals.css'
import {defineQuery} from 'groq'
import type {Metadata} from 'next'

export default function Home() {
return (
<div className="grid min-h-screen grid-rows-[20px_1fr_20px] items-center justify-items-center gap-16 p-8 pb-20 font-[family-name:var(--font-geist-sans)] sm:p-20">
<main className="row-start-2 flex flex-col items-center gap-8 sm:items-start">
<Image
className="dark:invert"
src="/next.svg"
alt="Next.js logo"
width={180}
height={38}
priority
/>
<ol className="list-inside list-decimal text-center font-[family-name:var(--font-geist-mono)] text-sm sm:text-left">
<li className="mb-2">
Get started by editing{' '}
<code className="rounded bg-black/[.05] px-1 py-0.5 font-semibold dark:bg-white/[.06]">
src/app/page.tsx
</code>
.
</li>
<li>Save and see your changes instantly.</li>
</ol>
const DEMO_QUERY = defineQuery(`*[_type == "demo" && slug.current == $slug][0].title`)
const slug = 'next-canary'

export async function generateMetadata(): Promise<Metadata> {
const {data} = await sanityFetch({query: DEMO_QUERY, params: {slug}})
return {
title: data || 'Next Canary',
}
}

<div className="flex flex-col items-center gap-4 sm:flex-row">
<a
className="bg-foreground text-background flex h-10 items-center justify-center gap-2 rounded-full border border-solid border-transparent px-4 text-sm transition-colors hover:bg-[#383838] sm:h-12 sm:px-5 sm:text-base dark:hover:bg-[#ccc]"
href="https://vercel.com/new?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
target="_blank"
rel="noopener noreferrer"
>
<Image
className="dark:invert"
src="/vercel.svg"
alt="Vercel logomark"
width={20}
height={20}
/>
Deploy now
</a>
<a
className="flex h-10 items-center justify-center rounded-full border border-solid border-black/[.08] px-4 text-sm transition-colors hover:border-transparent hover:bg-[#f2f2f2] sm:h-12 sm:min-w-44 sm:px-5 sm:text-base dark:border-white/[.145] dark:hover:bg-[#1a1a1a]"
href="https://nextjs.org/docs?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
target="_blank"
rel="noopener noreferrer"
>
Read our docs
</a>
</div>
</main>
<footer className="row-start-3 flex flex-wrap items-center justify-center gap-6">
<a
className="flex items-center gap-2 hover:underline hover:underline-offset-4"
href="https://nextjs.org/learn?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
target="_blank"
rel="noopener noreferrer"
>
<Image aria-hidden src="/file.svg" alt="File icon" width={16} height={16} />
Learn
</a>
<a
className="flex items-center gap-2 hover:underline hover:underline-offset-4"
href="https://vercel.com/templates?framework=next.js&utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
target="_blank"
rel="noopener noreferrer"
>
<Image aria-hidden src="/window.svg" alt="Window icon" width={16} height={16} />
Examples
</a>
<a
className="flex items-center gap-2 hover:underline hover:underline-offset-4"
href="https://nextjs.org?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
target="_blank"
rel="noopener noreferrer"
>
<Image aria-hidden src="/globe.svg" alt="Globe icon" width={16} height={16} />
Go to nextjs.org →
</a>
</footer>
</div>
export default async function Home() {
const {data} = await sanityFetch({query: DEMO_QUERY, params: {slug}})

return (
<h1 className="text-balance text-6xl font-bold leading-tight tracking-tighter lg:pr-8 lg:text-8xl">
{data || 'Next Canary'}
</h1>
)
}
8 changes: 8 additions & 0 deletions next-canary/src/sanity/client.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import {createClient} from '@sanity/client'

export const client = createClient({
projectId: 'hiomol4a',
dataset: 'lcapi',
apiVersion: '2024-09-18',
useCdn: false,
})
19 changes: 19 additions & 0 deletions next-canary/src/sanity/fetch.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import {type QueryParams} from '@sanity/client'
import {unstable_cacheTag as cacheTag} from 'next/cache'
import {client} from './client'

export async function sanityFetch<const QueryString extends string>({
query,
params = {},
}: {
query: QueryString
params?: QueryParams
}) {
'use cache'
const {result, syncTags} = await client.fetch(query, params, {
filterResponse: false,
})
cacheTag(...(syncTags as string[]))

return {data: result, tags: syncTags}
}

0 comments on commit 3cc0870

Please sign in to comment.