Open phymo opened 1 month ago
app/blog/[slug]/page.tsx
export default function Page({ params }: { params: { slug: string } }) {
return <div>My Post: {params.slug}</div>
}
However, slots are not route segments and do not affect the URL structure. For example, for /@analytics/views, the URL will be /views since @analytics is a slot.
Intercepting routes can be defined with the (..) convention, which is similar to relative path convention ../ but for segments.
You can use:
(.) to match segments on the same level (..) to match segments one level above (..)(..) to match segments two levels above (...) to match segments from the root app directory
// app/api/route.ts
export const dynamic = 'force-dynamic' // defaults to auto
export async function GET(request: Request) {}
caching/cookie/headers/streaming/cors
export const dynamic = 'auto' export const dynamicParams = true export const revalidate = false export const fetchCache = 'auto' export const runtime = 'nodejs' export const preferredRegion = 'auto'
The React components defined in special files of a route segment are rendered in a specific hierarchy:
'use client'
import { usePathname } from 'next/navigation'
import Link from 'next/link'
export default function Page() {
const pathname = usePathname()
return <Link href="/dashboard" scroll={false}>Dashboard</Link> // scroll={false} 切换时不保留 scroll位置
}
'use client'
import { useRouter } from 'next/navigation'
export default function Page() {
const router = useRouter()
return (
<button type="button" onClick={() => router.push('/dashboard')}>
Dashboard
</button>
)
}
Recommendation: Use the component to navigate between routes unless you have a specific requirement for using useRouter.
redirect
function: 307/303permanantRedirect
: 308useRouter
redirects
in next.config.js
NextResponse.redirect
To specifically handle errors in these root components, use a variation of error.js called app/global-error.js located in the root app directory.
app/global-error.tsx
'use client'
export default function GlobalError({
error,
reset,
}: {
error: Error & { digest?: string }
reset: () => void
}) {
return (
<html>
<body>
<h2>Something went wrong!</h2>
<button onClick={() => reset()}>Try again</button>
</body>
</html>
)
}
These steps are sequential and blocking, meaning the server can only render the HTML for a page once all the data has been fetched. And, on the client, React can only hydrate the UI once the code for all components in the page has been downloaded.
Streaming allows you to break down the page's HTML into smaller chunks and progressively send those chunks from the server to the client. This enables parts of the page to be displayed sooner, without waiting for all the data to load before any UI can be rendered.
import { Suspense } from 'react'
import { PostFeed, Weather } from './Components'
export default function Posts() {
return (
<section>
<Suspense fallback={<p>Loading feed...</p>}>
<PostFeed />
</Suspense>
<Suspense fallback={<p>Loading weather...</p>}>
<Weather />
</Suspense>
</section>
)
}
Use the file middleware.ts (or .js) in the root of your project to define Middleware.
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'
// This function can be marked `async` if using `await` inside
export function middleware(request: NextRequest) {
return NextResponse.redirect(new URL('/home', request.url))
}
// See "Matching Paths" below to learn more
export const config = {
matcher: '/about/:path*',
}
Structure