sanity
Version:
Sanity is a real-time content infrastructure with a scalable, hosted backend featuring a Graph Oriented Query Language (GROQ), asset pipelines and fast edge caches
41 lines (35 loc) • 1.58 kB
text/typescript
import {type SanityDocument} from '@sanity/types'
import {useEffect, useState} from 'react'
import {useAsObservable} from 'react-rx'
import {from, of} from 'rxjs'
import {catchError, debounceTime, switchMap} from 'rxjs/operators'
import {isRecord, useSource} from 'sanity'
const isSanityDocument = (value: unknown): value is SanityDocument =>
isRecord(value) && typeof value._id === 'string' && typeof value._type === 'string'
export function usePreviewUrl(value: Partial<SanityDocument> | undefined): string | undefined {
const [previewUrl, setPreviewUrl] = useState<string | undefined>(undefined)
const [error, setError] = useState<unknown>(null)
const {resolveProductionUrl} = useSource().document
// @todo refactor out of useAsObservable, and instead use `of() + useMemoObservable` like we did for `useLoadableFromCreateLoadable`
const value$ = useAsObservable(value)
if (error) throw error
useEffect(() => {
value$
.pipe(
// this so that the preview URL isn't fetched on every keystroke
debounceTime(500),
switchMap((document) =>
isSanityDocument(document) ? from(resolveProductionUrl({document})) : of(undefined),
),
catchError((e) => {
const message = isRecord(e) && typeof e.message === 'string' ? e.message : 'Unknown error'
throw new Error(`An error was thrown while trying to get your preview url: ${message}`)
}),
)
.subscribe({
next: setPreviewUrl,
error: setError,
})
}, [resolveProductionUrl, value$])
return previewUrl
}