Skip to content

Instantly share code, notes, and snippets.

@runeb
Last active May 9, 2022 07:22
Show Gist options
  • Save runeb/e59e07f1b89ae07c4819feddbfa027ca to your computer and use it in GitHub Desktop.
Save runeb/e59e07f1b89ae07c4819feddbfa027ca to your computer and use it in GitHub Desktop.
React hook for using a Sanity dataset as a general messaging system between users
import { useCallback, useEffect } from "react";
import type { SanityClient, SanityDocument } from "@sanity/client";
import {nanoid} from "nanoid"
type Params<T> = {
id: string;
client: SanityClient;
handler: (from: string, payload: T) => Promise<void>;
};
export function useSanityMessaging<T>({ id, handler, client }: Params<T>) {
type Message = SanityDocument<{
payload: T,
from: string
}>
// Sending a message to another party is done by creating a document with a
// known _type
const write = useCallback(
(to: string, payload: T) => {
client.create({
...{ payload },
from: id,
_id: `private.${nanoid()}`,
_type: `messages.${to}`,
});
},
[client, id]
);
// Receiving a message from another party is done by subscribing to created
// documents of a known _type
useEffect(() => {
const subscription = client
.listen<Message>("* [_type == $type]", { type: `messages.${id}` })
.subscribe((update) => {
if (update.transition === "appear") {
// A document of the _type we're interested in was created
const document = update.result;
const { from, payload, _id } = document;
// Tell our handler, then delete the document
handler(from, payload).then(() => client.delete(_id));
}
});
return () => subscription.unsubscribe();
}, [id, client]);
return write;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment