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