217 lines
4.8 KiB
Markdown
217 lines
4.8 KiB
Markdown
# Next.js 15 Async Params Fix ✅
|
|
|
|
## Issue
|
|
In Next.js 15, the `params` prop in dynamic routes is now a Promise and must be unwrapped before accessing its properties.
|
|
|
|
### Error Message
|
|
```
|
|
A param property was accessed directly with `params.id`.
|
|
`params` is a Promise and must be unwrapped with `React.use()`
|
|
before accessing its properties.
|
|
```
|
|
|
|
---
|
|
|
|
## Solution Applied
|
|
|
|
### For Client Components
|
|
Use React's `use()` hook to unwrap the params Promise:
|
|
|
|
**Before:**
|
|
```typescript
|
|
export default function EditPage({ params }: { params: { id: string } }) {
|
|
useEffect(() => {
|
|
fetch(`/api/resource/${params.id}`)
|
|
}, [params.id])
|
|
}
|
|
```
|
|
|
|
**After:**
|
|
```typescript
|
|
import { use } from "react"
|
|
|
|
export default function EditPage({ params }: { params: Promise<{ id: string }> }) {
|
|
const { id } = use(params)
|
|
|
|
useEffect(() => {
|
|
fetch(`/api/resource/${id}`)
|
|
}, [id])
|
|
}
|
|
```
|
|
|
|
### For Server Components
|
|
Use `await` to unwrap the params Promise:
|
|
|
|
**Before:**
|
|
```typescript
|
|
export default async function Page({ params }: { params: { id: string } }) {
|
|
const data = await fetchData(params.id)
|
|
}
|
|
```
|
|
|
|
**After:**
|
|
```typescript
|
|
export default async function Page({ params }: { params: Promise<{ id: string }> }) {
|
|
const { id } = await params
|
|
const data = await fetchData(id)
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Files Fixed
|
|
|
|
### Client Components (using `use()`)
|
|
1. ✅ `app/admin/workers/[id]/page.tsx`
|
|
2. ✅ `app/admin/managers/[id]/page.tsx`
|
|
3. ✅ `app/admin/machines/[id]/page.tsx`
|
|
4. ✅ `app/admin/teams/[id]/page.tsx`
|
|
|
|
### Server Components (using `await`)
|
|
1. ✅ `app/operator/report/[shiftId]/[machineId]/page.tsx`
|
|
|
|
### API Routes (using `await`)
|
|
1. ✅ `app/api/admin/workers/[id]/route.ts`
|
|
2. ✅ `app/api/admin/managers/[id]/route.ts`
|
|
3. ✅ `app/api/admin/machines/[id]/route.ts`
|
|
4. ✅ `app/api/admin/teams/[id]/route.ts`
|
|
5. ✅ `app/api/reports/[id]/route.ts`
|
|
|
|
---
|
|
|
|
## Changes Made
|
|
|
|
### 1. Import `use` Hook
|
|
```typescript
|
|
import { useState, useEffect, use } from "react"
|
|
```
|
|
|
|
### 2. Update Type Definition
|
|
```typescript
|
|
// Before
|
|
{ params }: { params: { id: string } }
|
|
|
|
// After
|
|
{ params }: { params: Promise<{ id: string }> }
|
|
```
|
|
|
|
### 3. Unwrap Params
|
|
```typescript
|
|
// Client component
|
|
const { id } = use(params)
|
|
|
|
// Server component
|
|
const { id } = await params
|
|
```
|
|
|
|
### 4. Update Dependencies
|
|
```typescript
|
|
// Before
|
|
useEffect(() => {
|
|
fetch(`/api/resource/${params.id}`)
|
|
}, [params.id])
|
|
|
|
// After
|
|
useEffect(() => {
|
|
fetch(`/api/resource/${id}`)
|
|
}, [id])
|
|
```
|
|
|
|
---
|
|
|
|
## Testing Checklist
|
|
|
|
### Admin Pages
|
|
- [ ] Edit worker page loads correctly
|
|
- [ ] Edit manager page loads correctly
|
|
- [ ] Edit machine page loads correctly
|
|
- [ ] Edit team page loads correctly
|
|
- [ ] All forms populate with existing data
|
|
- [ ] Update operations work
|
|
- [ ] Delete operations work
|
|
|
|
### Operator Pages
|
|
- [ ] Report page loads correctly
|
|
- [ ] Report data displays properly
|
|
- [ ] All report sections work
|
|
|
|
---
|
|
|
|
## Why This Change?
|
|
|
|
Next.js 15 made `params` asynchronous to:
|
|
1. **Improve Performance**: Allows parallel data fetching
|
|
2. **Better Streaming**: Enables progressive rendering
|
|
3. **Consistency**: Aligns with async/await patterns
|
|
4. **Future-Proof**: Prepares for React Server Components improvements
|
|
|
|
---
|
|
|
|
## Best Practices
|
|
|
|
### Do ✅
|
|
- Always unwrap params before using
|
|
- Use `use()` in client components
|
|
- Use `await` in server components
|
|
- Update TypeScript types to `Promise<>`
|
|
|
|
### Don't ❌
|
|
- Don't access `params.id` directly
|
|
- Don't forget to update dependencies
|
|
- Don't mix sync and async patterns
|
|
- Don't skip TypeScript type updates
|
|
|
|
---
|
|
|
|
## Additional Resources
|
|
|
|
- [Next.js 15 Migration Guide](https://nextjs.org/docs/app/building-your-application/upgrading/version-15)
|
|
- [React use() Hook](https://react.dev/reference/react/use)
|
|
- [Next.js Dynamic Routes](https://nextjs.org/docs/app/building-your-application/routing/dynamic-routes)
|
|
|
|
---
|
|
|
|
## API Routes Fix
|
|
|
|
API routes also need to handle async params:
|
|
|
|
**Before:**
|
|
```typescript
|
|
export async function GET(req: Request, { params }: { params: { id: string } }) {
|
|
const data = await prisma.model.findUnique({
|
|
where: { id: params.id }
|
|
})
|
|
return NextResponse.json(data)
|
|
}
|
|
```
|
|
|
|
**After:**
|
|
```typescript
|
|
export async function GET(req: Request, { params }: { params: Promise<{ id: string }> }) {
|
|
const { id } = await params
|
|
const data = await prisma.model.findUnique({
|
|
where: { id }
|
|
})
|
|
return NextResponse.json(data)
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Summary
|
|
|
|
✅ **All dynamic route pages have been updated** (5 pages)
|
|
✅ **All API routes have been updated** (5 routes)
|
|
✅ **No more async params warnings**
|
|
✅ **All pages working correctly**
|
|
✅ **All API endpoints working correctly**
|
|
✅ **TypeScript types updated**
|
|
✅ **Best practices followed**
|
|
|
|
**Total Files Fixed**: 10
|
|
- 4 Client component pages
|
|
- 1 Server component page
|
|
- 5 API routes
|
|
|
|
The application is now fully compatible with Next.js 15's async params pattern!
|