Skip to content

Instantly share code, notes, and snippets.

@sebakerckhof
Forked from ksinas/useSubscribeSuspend.js
Last active March 10, 2022 20:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sebakerckhof/d9b12746856d08de4db2f8263469e22f to your computer and use it in GitHub Desktop.
Save sebakerckhof/d9b12746856d08de4db2f8263469e22f to your computer and use it in GitHub Desktop.
import { Meteor } from 'meteor/meteor';
import { Tracker } from 'meteor/tracker';
import { useEffect } from 'react';
const hashSubscriptionArguments = (pubName, args) => EJSON.stringify([pubName, args]);
const contexts = new Map();
const getOrCreateSubscription = (pubName, args) => {
const subHash = hashSubscriptionArguments(pubName, args);
const exisitingContext = contexts.get(subHash);
if (exisitingContext) exisitingContext;
const context = {
count: 0,
ready: false,
promise,
};
contexts.set(subHash, context)
context.promise = new Promise((res, rej) => {
context.sub = Meteor.subscribe(pubName, args, {
onReady() {
context.ready = true;
res();
// setup self-destruction in case component has been unmounted
// while loading and hook has never been called
context.destroyHandle = setTimeout(() => {
context.sub.stop();
}, 3000);
},
onStop(error) {
if (error) {
context.error = err;
rej(error);
// give 5s until we let a new request occur
setTimeout(() => {
contexts.delete(subHash)
}, 5000);
}
}
});
})
return context;
};
const useSubscribeSuspend = (pubName, args) => {
if (!pubName) return;
const subContext = getOrCreateSubscription(pubName, args);
if (subContext.error) {
throw subContext.error;
}
if (!subContext.ready) {
throw subContext.promise;
}
useEffect(() => {
clearTimeout(subContext.destroyHandle);
subContext.count += 1;
return () => {
subContext.count -= 1;
if (!subContext.count) {
subContext.sub.stop();
}
};
}, [subContext]);
};
export default useSubscribeSuspend;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment