@@ -372,43 +372,58 @@ export function useTracker<T, K extends undefined | T = undefined>(
372372 return meteorData
373373}
374374
375- function useReadyState ( ) : {
376- ready : boolean
377- setReady : ( value : boolean ) => void
378- cancelPreviousReady : ( timeout : number ) => void
375+ /**
376+ * A hook to track a boolean state with a sort of histeresis, with preference for `true`. `setState` makes the returned
377+ * `state` be `true` immediately, but `false` only after `resetState` is called and `timeout` elapses. If `setState`
378+ * is called with `true` before `timeout` elapses, then `resetState` is aborted and `state` will remain `ture.
379+ *
380+ * Later `resetState` calls replace earlier unelapsed calls and their timeout periods.
381+ *
382+ * @param {boolean } [initialState=false]
383+ * @return {* } {{
384+ * state: boolean
385+ * setState: (value: boolean) => void
386+ * resetState: (timeout: number) => void
387+ * }}
388+ */
389+ function useDelayState ( initialState = false ) : {
390+ state : boolean
391+ setState : ( value : boolean ) => void
392+ resetState : ( timeout : number ) => void
379393} {
380- const [ ready , setReady ] = useState ( false )
381- const [ prevReady , setPrevReady ] = useState ( false )
394+ const [ state , setState ] = useState ( initialState )
395+ const [ prevState , setPrevState ] = useState ( initialState )
382396 const prevReadyTimeoutRef = useRef < number | null > ( null )
383397
384- const setIsReady = useCallback (
398+ const setStateAndClearResets = useCallback (
385399 ( value : boolean ) => {
386- setReady ( value )
400+ setState ( value )
387401
388402 if ( value ) {
389- setPrevReady ( true )
403+ setPrevState ( true )
390404 if ( prevReadyTimeoutRef . current !== null ) {
391405 window . clearTimeout ( prevReadyTimeoutRef . current )
392406 prevReadyTimeoutRef . current = null
393407 }
394408 }
395409 } ,
396- [ setReady , setPrevReady ]
410+ [ setState , setPrevState ]
397411 )
398412
399- const cancelPrevReady = useCallback (
400- ( timeout : number ) => {
401- prevReadyTimeoutRef . current = window . setTimeout ( ( ) => {
402- setPrevReady ( false )
403- } , timeout )
404- } ,
405- [ prevReadyTimeoutRef ]
406- )
413+ const resetStateAfterDelay = useCallback ( ( timeout : number ) => {
414+ if ( prevReadyTimeoutRef . current !== null ) {
415+ window . clearTimeout ( prevReadyTimeoutRef . current )
416+ }
417+ prevReadyTimeoutRef . current = window . setTimeout ( ( ) => {
418+ prevReadyTimeoutRef . current = null
419+ setPrevState ( false )
420+ } , timeout )
421+ } , [ ] )
407422
408423 return {
409- ready : ready || prevReady ,
410- setReady : setIsReady ,
411- cancelPreviousReady : cancelPrevReady ,
424+ state : state || prevState ,
425+ setState : setStateAndClearResets ,
426+ resetState : resetStateAfterDelay ,
412427 }
413428}
414429
@@ -425,7 +440,7 @@ export function useSubscription<K extends keyof AllPubSubTypes>(
425440 sub : K ,
426441 ...args : Parameters < AllPubSubTypes [ K ] >
427442) : boolean {
428- const { ready, setReady, cancelPreviousReady } = useReadyState ( )
443+ const { state : ready , setState : setReady , resetState : cancelPreviousReady } = useDelayState ( )
429444
430445 useEffect ( ( ) => {
431446 const subscription = Tracker . nonreactive ( ( ) => meteorSubscribe ( sub , ...args ) )
@@ -465,7 +480,7 @@ export function useSubscriptionIfEnabled<K extends keyof AllPubSubTypes>(
465480 enable : boolean ,
466481 ...args : Parameters < AllPubSubTypes [ K ] >
467482) : boolean {
468- const { ready, setReady, cancelPreviousReady } = useReadyState ( )
483+ const { state : ready , setState : setReady , resetState : cancelPreviousReady } = useDelayState ( )
469484
470485 useEffect ( ( ) => {
471486 if ( ! enable ) {
@@ -510,7 +525,7 @@ export function useSubscriptionIfEnabledReadyOnce<K extends keyof AllPubSubTypes
510525 enable : boolean ,
511526 ...args : Parameters < AllPubSubTypes [ K ] >
512527) : boolean {
513- const { ready, setReady, cancelPreviousReady } = useReadyState ( )
528+ const { state : ready , setState : setReady , resetState : cancelPreviousReady } = useDelayState ( )
514529
515530 useEffect ( ( ) => {
516531 if ( ! enable ) {
0 commit comments