Last active
December 8, 2021 10:30
-
-
Save SimeonGriggs/0a1e1a6d86af70ba7ee863f9bb5dfaf9 to your computer and use it in GitHub Desktop.
A "listening" version of usePreviewSubscription() that re-queries the client. Not yet recommended for Production use.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const { data, loading } = useListeningQuery( | |
query, | |
{ | |
params: params ?? {}, | |
initialData: page, | |
enabled: preview, | |
delay: 250, | |
} | |
); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import {createClient} from 'next-sanity' | |
import {config} from './config' | |
// Set up the client for fetching data in the getProps page functions | |
export const sanityClient = createClient(config) | |
// Listener client uses credentials to fetch drafts as it's used client-side | |
export const listenerClient = createClient({ | |
...config, | |
useCdn: false, | |
withCredentials: true | |
}) | |
// Set up a preview client with serverless authentication for drafts | |
export const previewClient = createClient({ | |
...config, | |
useCdn: false, | |
token: process.env.SANITY_API_TOKEN, | |
}) | |
// Helper function for easily switching between normal client and preview client | |
export const getClient = (usePreview) => usePreview ? previewClient : sanityClient |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { useEffect, useState } from "react"; | |
import { extract } from "@sanity/mutator"; | |
import debounce from "lodash/debounce"; | |
import { listenerClient } from "../lib/sanity.server"; | |
const useListeningQuery = (query, config) => { | |
const { params = {}, initialData, enabled = false, delay = 1000 } = config; | |
const [data, setData] = useState(initialData); | |
const [loading, setLoading] = useState(false); | |
// Find the ids of documents we want to listen to changes on | |
// Maybe: Should include draft.ids of each as well? | |
const references = extract(`.._ref`, initialData); | |
const ids = extract(`.._id`, initialData); | |
const docIds = Array.from(new Set([...references, ...ids])).filter( | |
(id) => !id.startsWith("image-") && !id.startsWith("file-") | |
); | |
function fetchData() { | |
// This isn't a great place to put this because it only triggers when fetch starts, | |
// Not when listener starts receiving updates | |
// Perhaps we could have isListening + isLoading | |
setLoading(true) | |
// Listener client uses credentials to fetch draft content | |
listenerClient | |
.fetch(query, params) | |
.then((newData) => { | |
setData(newData) | |
setLoading(false) | |
}); | |
} | |
useEffect(() => { | |
let subscription; | |
if (enabled) { | |
// Do we even need to fetch immediately if we already have data? | |
// Probably not | |
// fetchData(); | |
// We're not listening to the passed-in query | |
// We listen for changes on any of the initialData's _id's and _ref's | |
subscription = listenerClient | |
.listen(`*[_id in $docIds]`, { docIds }, { includeResult: false }) | |
.subscribe( | |
debounce(() => { | |
// console.log(`Debounced fetch`) | |
fetchData() | |
// For some reason it helps to have a delayed additional fetch | |
// The last keystroke doesn't always trigger a refetch | |
// TODO: Understand why and fix this | |
setTimeout(() => { | |
// console.log(`Debounced extra fetch`) | |
fetchData() | |
}, delay); | |
}, delay) | |
); | |
} | |
return () => { | |
if (subscription) { | |
subscription.unsubscribe(); | |
} | |
}; | |
}, [initialData]); | |
return { data, loading }; | |
}; | |
export default useListeningQuery; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment