diff --git a/packages/react-mongo/react-mongo.ts b/packages/react-mongo/react-mongo.ts index 6d2538b..c2a4178 100644 --- a/packages/react-mongo/react-mongo.ts +++ b/packages/react-mongo/react-mongo.ts @@ -1,30 +1,30 @@ import { Meteor } from 'meteor/meteor' import { Mongo } from 'meteor/mongo' import { Tracker } from 'meteor/tracker' -import { useEffect, useMemo, useReducer, useRef, DependencyList } from 'react' +import { + useEffect, + useMemo, + useReducer, + useRef, + useCallback, + DependencyList, +} from 'react' const fur = (x: number): number => x + 1 const useForceUpdate = () => useReducer(fur, 0)[1] -const useSubscriptionClient = (factory: () => Meteor.SubscriptionHandle | void, deps: DependencyList= []) => { - const forceUpdate = useForceUpdate() - const { current: refs } = useRef<{ - handle?: Meteor.SubscriptionHandle, - updateOnReady: boolean - }>({ - handle: { - stop () { - refs.handle?.stop() - }, - ready () { - refs.updateOnReady = true - return refs.handle?.ready() - } - }, - updateOnReady: false - }) +const useSubscriptionClient = ( + name: string | false, + args: any[] +) => { + const subscription = useRef() useEffect(() => { + if (!name) { + subscription.current = null + return + } + // Use Tracker.nonreactive in case we are inside a Tracker Computation. // This can happen if someone calls `ReactDOM.render` inside a Computation. // In that case, we want to opt out of the normal behavior of nested @@ -32,20 +32,31 @@ const useSubscriptionClient = (factory: () => Meteor.SubscriptionHandle | void, // it stops the inner one. const computation = Tracker.nonreactive(() => ( Tracker.autorun(() => { - refs.handle = factory() - if (!refs.handle) return - if (refs.updateOnReady && refs.handle.ready()) { - forceUpdate() - } + subscription.current = Meteor.subscribe( name, ...args ) + // @ts-ignore this is just an internal thing + subscription.current.deps = { name, args } }) )) - return () => { - computation.stop() - } - }, deps) + return () => computation.stop() + }, [name, ...args]) + + return useCallback( + () => { + if (subscription.current) { + // @ts-ignore + const { deps } = subscription.current + if (deps.name === name && deps.args === args) { + return subscription.current.ready() + } else { + // Prevented returning the previous subscription's status + } + } - return refs.handle + return false + }, + [name, ...args] + ) } const useSubscriptionServer = (): Meteor.SubscriptionHandle => ({ @@ -53,10 +64,10 @@ const useSubscriptionServer = (): Meteor.SubscriptionHandle => ({ ready() { return true } }) -export const useSubscription = (factory: () => Meteor.SubscriptionHandle | void, deps: DependencyList = []) => ( +export const useSubscription = (name: string | false, ...args: any[]) => ( Meteor.isServer ? useSubscriptionServer() - : useSubscriptionClient(factory, deps) + : useSubscriptionClient(name, args) ) const useCursorClient = (factory: () => Mongo.Cursor, deps: DependencyList = []) => { diff --git a/packages/react-mongo/types/react-mongo.d.ts b/packages/react-mongo/types/react-mongo.d.ts index f09637b..2ae352c 100644 --- a/packages/react-mongo/types/react-mongo.d.ts +++ b/packages/react-mongo/types/react-mongo.d.ts @@ -1,10 +1,9 @@ -import { Meteor } from 'meteor/meteor'; import { Mongo } from 'meteor/mongo'; import { DependencyList } from 'react'; declare type UseSubscriptionOptions = { deps?: DependencyList; updateOnReady?: boolean; }; -export declare const useSubscription: (factory: () => Meteor.SubscriptionHandle | void, deps?: DependencyList | UseSubscriptionOptions) => void; +export declare const useSubscription: (name: string | false, args: any[]) => () => boolean; export declare const useCursor: (factory: () => Mongo.Cursor, deps?: DependencyList) => Mongo.Cursor; export {};