next.js/packages/next/src/client/components/use-offline.tsx
use-offline.tsx56 lines1.5 KB
'use client'

import React, {
  createContext,
  useContext,
  useState,
  useOptimistic,
  startTransition,
} from 'react'

const OfflineContext = createContext<boolean>(false)

// Module-level reference to the optimistic setter. Assigned inside the
// provider component on every render. Called by the offline module
// (via dispatchOfflineChange) to update the React tree.
let setOptimistic: ((value: boolean) => void) | null = null
let setCanonical: ((value: boolean) => void) | null = null

/**
 * Called by the offline module when the offline state changes.
 * Dispatches into React via startTransition + useOptimistic.
 */
export function dispatchOfflineChange(isOffline: boolean): void {
  const canonical = setCanonical
  const optimistic = setOptimistic
  if (canonical === null || optimistic === null) {
    return
  }
  startTransition(() => {
    canonical(isOffline)
    optimistic(isOffline)
  })
}

export function OfflineProvider({ children }: { children: React.ReactNode }) {
  const [canonicalOffline, setCanonicalOffline] = useState(false)
  const [isOffline, setOptimisticOffline] = useOptimistic(canonicalOffline)

  setOptimistic = setOptimisticOffline
  setCanonical = setCanonicalOffline

  return (
    <OfflineContext.Provider value={isOffline}>
      {children}
    </OfflineContext.Provider>
  )
}

/**
 * Returns whether the app is currently offline.
 * Returns `false` during SSR and hydration.
 */
export function useOffline(): boolean {
  return useContext(OfflineContext)
}
Quest for Codev2.0.0
/
SIGN IN