Last active
May 16, 2022 12:17
-
-
Save dr-skot/0fbdb95b4415e29be5b1beb73e8b2045 to your computer and use it in GitHub Desktop.
Utilities for using the Parse Platform with nextjs. Prefer this to @parse/react-ssr
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 BrowserParse from 'parse'; | |
import ServerParse from 'parse/node'; | |
import _ from 'lodash'; | |
const isBrowser = !!global.window; | |
const Parse = isBrowser ? BrowserParse : ServerParse; | |
export default Parse; | |
export function initialize(serverURL: string, applicationId: string, javascriptKey: string): void { | |
Parse.serverURL = serverURL; | |
Parse.initialize(applicationId, javascriptKey); | |
if (isBrowser) Parse.enableLocalDatastore(); | |
} | |
// useful for relationship querying | |
export function stub(className: string, id?: string): Parse.Object | undefined { | |
if (!id) return undefined; | |
const stub = new Parse.Object(className); | |
stub.id = id; | |
return stub; | |
} | |
// converts parse object to plain-old-javascript-object | |
export function pojo(parseObject?: Parse.Object): unknown { | |
if (!parseObject) return undefined; | |
return _.mapValues({ id: parseObject.id, ...parseObject.attributes }, (value: unknown) => | |
value instanceof Parse.Object | |
? pojo(value) | |
: _.isDate(value) | |
? (value as Date).getTime() | |
: value | |
); | |
} | |
export { useLiveQuery } from './useLiveQuery' |
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 Parse from './Parse'; | |
import { useEffect, useRef, useState } from 'react'; | |
const RETRY_INTERVAL = 2000; | |
export function useLiveQuery(query: Parse.Query): { results?: Parse.Object[]; isLive: boolean } { | |
const subscriptionRef = useRef<{ unsubscribe: () => void }>(); | |
const [results, setResults] = useState<Parse.Object[]>(); | |
const [isLive, setIsLive] = useState(false); | |
const [isLoading, setIsLoading] = useState(false); | |
const [retries, setRetries] = useState(0); | |
const encodedQuery = encodeQuery(query); | |
useEffect(() => { | |
if (!navigator.onLine) return; | |
// (re)load the results | |
setIsLoading(true); | |
query.find().then((result) => { | |
setResults(result); | |
setIsLoading(false); | |
}); | |
// handle add/update/remove | |
const add = (object: Parse.Object) => setResults((prevs) => [...(prevs || []), object]); | |
const update = (object: Parse.Object) => | |
setResults((prevs) => (prevs || []).map((prev) => (prev.id === object.id ? object : prev))); | |
const remove = (object: Parse.Object) => | |
setResults((prevs) => (prevs || []).filter((prev) => prev.id !== object.id)); | |
const open = () => setIsLive(true); | |
const close = () => setIsLive(false); | |
// subscribe and listen for add/update/remove events | |
query.subscribe().then((subscription) => { | |
subscriptionRef.current = subscription; | |
subscription.on('open', open); | |
subscription.on('create', add); | |
subscription.on('update', update); | |
subscription.on('enter', add); | |
subscription.on('leave', remove); | |
subscription.on('delete', remove); | |
subscription.on('close', close); | |
window.addEventListener('offline', close); | |
}); | |
return () => { | |
subscriptionRef.current?.unsubscribe(); | |
window.removeEventListener('offline', close); | |
}; | |
// eslint-disable-next-line react-hooks/exhaustive-deps | |
}, [encodedQuery, retries]); | |
// retry until isLive | |
useEffect(() => { | |
if (isLive) return; | |
const retry = () => setRetries((prev) => prev + 1); | |
const interval = window.setInterval(retry, RETRY_INTERVAL); | |
return () => window.clearInterval(interval); | |
}, [isLive]); | |
return { results, isLive: isLive && !isLoading }; | |
} | |
function encodeQuery(query: Parse.Query): string { | |
const encoded = { | |
className: query.className, | |
query: query.toJSON(), | |
}; | |
return JSON.stringify(encoded); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment