104 lines
3.0 KiB
Markdown
104 lines
3.0 KiB
Markdown
# SSR 錯誤修復總結
|
|
|
|
## 🐛 問題描述
|
|
|
|
在 Next.js 應用中遇到了 `ReferenceError: window is not defined` 錯誤,這是因為在服務器端渲染 (SSR) 時嘗試訪問 `window` 對象導致的。
|
|
|
|
## ✅ 修復的文件
|
|
|
|
### 1. `components/admin/admin-layout.tsx`
|
|
**問題**:在 SSR 期間直接使用 `window` 對象
|
|
**修復**:添加 `typeof window !== 'undefined'` 檢查
|
|
|
|
```typescript
|
|
// 修復前
|
|
{window.opener && !window.opener.closed && (
|
|
<Button onClick={() => {
|
|
window.opener.focus()
|
|
window.close()
|
|
}}>
|
|
關閉頁面
|
|
</Button>
|
|
)}
|
|
|
|
// 修復後
|
|
{typeof window !== 'undefined' && window.opener && !window.opener.closed && (
|
|
<Button onClick={() => {
|
|
window.opener.focus()
|
|
window.close()
|
|
}}>
|
|
關閉頁面
|
|
</Button>
|
|
)}
|
|
```
|
|
|
|
### 2. `components/admin/user-management.tsx`
|
|
**問題**:在函數中直接使用 `window.location.origin`
|
|
**修復**:添加條件檢查,提供回退值
|
|
|
|
```typescript
|
|
// 修復前
|
|
const invitationLink = `${window.location.origin}/register?token=${invitationToken}&email=${encodeURIComponent(inviteEmail)}&role=${inviteRole}`
|
|
|
|
// 修復後
|
|
const invitationLink = typeof window !== "undefined"
|
|
? `${window.location.origin}/register?token=${invitationToken}&email=${encodeURIComponent(inviteEmail)}&role=${inviteRole}`
|
|
: `/register?token=${invitationToken}&email=${encodeURIComponent(inviteEmail)}&role=${inviteRole}`
|
|
```
|
|
|
|
## 🔧 修復策略
|
|
|
|
### 1. 條件檢查
|
|
```typescript
|
|
if (typeof window !== 'undefined') {
|
|
// 只在客戶端執行
|
|
window.location.href = "/"
|
|
}
|
|
```
|
|
|
|
### 2. 三元運算符
|
|
```typescript
|
|
const url = typeof window !== 'undefined'
|
|
? `${window.location.origin}/path`
|
|
: "/path"
|
|
```
|
|
|
|
### 3. useEffect Hook
|
|
```typescript
|
|
useEffect(() => {
|
|
// 只在客戶端執行
|
|
window.addEventListener('resize', handleResize)
|
|
return () => window.removeEventListener('resize', handleResize)
|
|
}, [])
|
|
```
|
|
|
|
## 📋 已檢查的文件
|
|
|
|
以下文件已經有正確的 SSR 處理,無需修復:
|
|
- `components/ui/use-mobile.tsx` - 使用 useEffect
|
|
- `components/admin/competition-management.tsx` - 有條件檢查
|
|
- `components/admin/scoring-link-dialog.tsx` - 有條件檢查
|
|
|
|
## 🎯 修復結果
|
|
|
|
- ✅ 消除了 `window is not defined` 錯誤
|
|
- ✅ 保持了客戶端功能正常運作
|
|
- ✅ 確保了 SSR 兼容性
|
|
- ✅ 提供了適當的回退值
|
|
|
|
## 📝 最佳實踐
|
|
|
|
1. **始終檢查 `window` 對象**:在 Next.js 中,`window` 只在客戶端可用
|
|
2. **使用 useEffect**:對於需要在客戶端執行的代碼,使用 `useEffect` Hook
|
|
3. **提供回退值**:為 SSR 環境提供適當的默認值
|
|
4. **避免在組件頂層使用 `window`**:將 `window` 相關代碼放在函數內部或 useEffect 中
|
|
|
|
## 🚀 測試建議
|
|
|
|
1. 檢查管理員頁面是否正常加載
|
|
2. 驗證用戶邀請功能是否正常
|
|
3. 確認彈窗關閉功能是否正常
|
|
4. 測試在不同環境下的表現
|
|
|
|
修復完成後,應用應該能夠正常進行服務器端渲染,同時保持所有客戶端功能正常運作。
|