go.charczuk.com@v0.0.0-20240327042549-bc490516bd1a/projects/chirp/pkg/static/_nextjs/src/components/sessionProvider.tsx (about)

     1  /**
     2   * Copyright (c) 2024 - Present. Will Charczuk. All rights reserved.
     3   * Use of this source code is governed by a MIT license that can be found in the LICENSE file at the root of the repository.
     4   */
     5  import { Spinner } from '@blueprintjs/core';
     6  import { Session } from '../app/api';
     7  import React, { useContext, useState, useEffect } from 'react';
     8  import useSWR from 'swr'
     9  
    10  type SessionProviderProps = {
    11    children: React.ReactNode
    12    baseURL?: string
    13  };
    14  
    15  export const SessionContext = React.createContext?.<
    16    Session | undefined
    17  >(undefined)
    18  
    19  export function useSession(): Session {
    20    if (!SessionContext) {
    21      throw new Error("React Context is unavailable in Server Components")
    22    }
    23    // @ts-expect-error Satisfy TS if branch on line below
    24    const value: Session = useContext(SessionContext)
    25    if (!value) {
    26      throw new Error(
    27        "`useSession` must be wrapped in a <SessionProvider />"
    28      )
    29    }
    30    return value
    31  }
    32  
    33  const fetcher = async (url: string): Promise<Session> => {
    34    const r = await fetch(url)
    35    const data = await r.json()
    36    return data as Session
    37  }
    38  
    39  export function SessionProvider(props: SessionProviderProps) {
    40    if (!SessionContext) {
    41      throw new Error("React Context is unavailable in Server Components")
    42    }
    43    const { data, isLoading } = useSWR('/api/v1/session', fetcher)
    44    if (!isLoading) {
    45      return (
    46        <Spinner />
    47      )
    48    }
    49    return (
    50      <SessionContext.Provider value={data}>{props.children}</SessionContext.Provider>
    51    )
    52  }