👁️
5
fork

Configure Feed

Select the types of activity you want to include in your feed.

new error component!

+103
+101
src/components/RouteErrorComponent.tsx
··· 1 + import type { ErrorComponentProps } from "@tanstack/react-router"; 2 + import { Link, useRouter } from "@tanstack/react-router"; 3 + import { AlertTriangle, Check, Copy, Home, RefreshCw } from "lucide-react"; 4 + import { useState } from "react"; 5 + 6 + export function RouteErrorComponent({ 7 + error, 8 + info, 9 + reset, 10 + }: ErrorComponentProps) { 11 + const router = useRouter(); 12 + const [copied, setCopied] = useState(false); 13 + 14 + const copyErrorDetails = async () => { 15 + const details = [ 16 + `Error: ${error.message}`, 17 + `URL: ${window.location.href}`, 18 + `Time: ${new Date().toISOString()}`, 19 + `User Agent: ${navigator.userAgent}`, 20 + "", 21 + "Stack Trace:", 22 + error.stack || "(no stack trace)", 23 + "", 24 + ...(info?.componentStack 25 + ? ["Component Stack:", info.componentStack] 26 + : []), 27 + ].join("\n"); 28 + 29 + await navigator.clipboard.writeText(details); 30 + setCopied(true); 31 + setTimeout(() => setCopied(false), 2000); 32 + }; 33 + 34 + return ( 35 + <div className="min-h-screen bg-white dark:bg-slate-900 flex items-center justify-center p-6"> 36 + <div className="max-w-4xl w-full"> 37 + <div className="bg-red-50 dark:bg-red-900/20 border border-red-200 dark:border-red-800 rounded-lg p-6"> 38 + <div className="flex items-start gap-4"> 39 + <div className="p-2 bg-red-100 dark:bg-red-900/40 rounded-full"> 40 + <AlertTriangle className="w-6 h-6 text-red-600 dark:text-red-400" /> 41 + </div> 42 + <div className="flex-1 min-w-0"> 43 + <h1 className="text-xl font-bold text-red-900 dark:text-red-100 mb-2"> 44 + Something went wrong 45 + </h1> 46 + <p className="text-red-700 dark:text-red-300 mb-4"> 47 + {error.message || "An unexpected error occurred"} 48 + </p> 49 + 50 + <div className="flex flex-wrap gap-3 mb-4"> 51 + <button 52 + type="button" 53 + onClick={() => { 54 + reset(); 55 + router.invalidate(); 56 + }} 57 + className="inline-flex items-center gap-2 px-4 py-2 bg-red-600 hover:bg-red-700 text-white font-medium rounded-lg transition-colors" 58 + > 59 + <RefreshCw className="w-4 h-4" /> 60 + Try again 61 + </button> 62 + <button 63 + type="button" 64 + onClick={copyErrorDetails} 65 + className="inline-flex items-center gap-2 px-4 py-2 bg-gray-200 dark:bg-slate-700 hover:bg-gray-300 dark:hover:bg-slate-600 text-gray-900 dark:text-white font-medium rounded-lg transition-colors" 66 + > 67 + {copied ? ( 68 + <Check className="w-4 h-4" /> 69 + ) : ( 70 + <Copy className="w-4 h-4" /> 71 + )} 72 + {copied ? "Copied!" : "Copy details"} 73 + </button> 74 + <Link 75 + to="/" 76 + className="inline-flex items-center gap-2 px-4 py-2 bg-gray-200 dark:bg-slate-700 hover:bg-gray-300 dark:hover:bg-slate-600 text-gray-900 dark:text-white font-medium rounded-lg transition-colors" 77 + > 78 + <Home className="w-4 h-4" /> 79 + Go home 80 + </Link> 81 + </div> 82 + 83 + {import.meta.env.DEV && ( 84 + <div className="space-y-2"> 85 + <pre className="text-xs bg-red-100 dark:bg-red-900/30 p-3 rounded overflow-x-auto text-red-800 dark:text-red-200 whitespace-pre-wrap break-words max-h-64 overflow-y-auto"> 86 + {error.stack || error.message} 87 + </pre> 88 + {info?.componentStack && ( 89 + <pre className="text-xs bg-red-100 dark:bg-red-900/30 p-3 rounded overflow-x-auto text-red-800 dark:text-red-200 whitespace-pre-wrap break-words max-h-48 overflow-y-auto"> 90 + {info.componentStack} 91 + </pre> 92 + )} 93 + </div> 94 + )} 95 + </div> 96 + </div> 97 + </div> 98 + </div> 99 + </div> 100 + ); 101 + }
+2
src/router.tsx
··· 1 1 import { createRouter } from "@tanstack/react-router"; 2 2 import { setupRouterSsrQueryIntegration } from "@tanstack/react-router-ssr-query"; 3 + import { RouteErrorComponent } from "./components/RouteErrorComponent"; 3 4 import * as TanstackQuery from "./integrations/tanstack-query/root-provider"; 4 5 5 6 // Import the generated route tree ··· 13 14 routeTree, 14 15 context: { ...rqContext }, 15 16 defaultPreload: "intent", 17 + defaultErrorComponent: RouteErrorComponent, 16 18 pathParamsAllowedCharacters: [":"], 17 19 Wrap: (props: { children: React.ReactNode }) => { 18 20 return (