nextjs-demo

next.js demo using react 19 rc

git clone https://9o.is/git/nextjs-demo.git

Alert.tsx

(2022B)


      1 import { Component, createContext, ReactNode, useContext, useState } from "react"
      2 
      3 type AlertBoundaryContext = {
      4     error?: Error
      5     setError: (error: Error) => void
      6 }
      7 
      8 const AlertBoundaryContext = createContext<AlertBoundaryContext | undefined>(undefined)
      9 
     10 export const useAlertBoundaryContext = () => {
     11     const context = useContext(AlertBoundaryContext)
     12     if (!context) throw new Error('useAlertBoundaryContext() must be used with <AlertBoundary/>')
     13     return context
     14 }
     15 
     16 export const Alert = () => {
     17     const { error } = useAlertBoundaryContext()
     18 
     19     return (
     20         <div role="alert">
     21             {error?.message ?? null}
     22         </div>
     23     )
     24 }
     25 
     26 type AlertContextProps = {
     27     children: ReactNode
     28 }
     29 
     30 const AlertContext = ({ children }: AlertContextProps) => {
     31     const [error, setError] = useState<Error>()
     32 
     33     return (
     34         <AlertBoundaryContext.Provider value={{ error, setError }}>
     35             {children}
     36         </AlertBoundaryContext.Provider>
     37     )
     38 }
     39 
     40 type ErrorBoundaryProps = {
     41     children: ReactNode
     42     fallback?: ReactNode
     43 }
     44 
     45 type ErrorBoundaryState = {
     46     error?: Error
     47 }
     48 
     49 export class ErrorBoundary extends Component<ErrorBoundaryProps, ErrorBoundaryState> {
     50     static contextType = AlertBoundaryContext
     51     context!: React.ContextType<typeof AlertBoundaryContext>;
     52     
     53     constructor(props: ErrorBoundaryProps) {
     54         super(props)
     55         this.state = {}
     56     }
     57 
     58     static getDerivedStateFromError(error: Error): ErrorBoundaryState {
     59         return { error }
     60     }
     61 
     62     componentDidCatch(error: Error) {
     63         if (!this.context) throw new Error('<Alert.ErrorBoundary/> must be used within <Alert.Context/>')
     64         this.context.setError(error)
     65         console.log('error boundaary', error)
     66     }
     67 
     68     render() {
     69         const { error } = this.state
     70         const { children, fallback } = this.props
     71 
     72         return (
     73             <>
     74                 {!error ? children : fallback}
     75             </>
     76         )
     77     }
     78 }
     79 
     80 Alert.Context = AlertContext
     81 Alert.ErrorBoundary = ErrorBoundary