This error occurs when trying to use getServerSideProps outside of page components in Next.js. The function must be exported from files in the /pages directory, not from regular components or when using the App Router.
This error indicates that you're attempting to export getServerSideProps from a location where Next.js doesn't support it. getServerSideProps is a special Next.js function designed exclusively for server-side data fetching in page components within the Pages Router. The function must be exported as a named export from a file located in the /pages directory. It cannot be used in regular React components, API routes, or attached as a method to a component class. Next.js enforces this restriction because getServerSideProps is part of the build-time and runtime contract for page-level server-side rendering. With Next.js 13+ and the App Router (/app directory), this function is completely deprecated in favor of async Server Components and the fetch API, which provide a more flexible and modern approach to data fetching.
Ensure your file is located in the /pages directory (or a subdirectory of it) if using the Pages Router. Only files in this directory can export getServerSideProps:
# Correct structure
pages/
index.tsx # ✓ Can use getServerSideProps
products/
[id].tsx # ✓ Can use getServerSideProps
api/
users.ts # ✗ API routes cannot use it
components/
ProductCard.tsx # ✗ Regular components cannot use itIf your file is not in the pages directory, move it there or restructure your code.
Make sure getServerSideProps is exported as a standalone function, not attached to the component:
// ✓ CORRECT: Separate named export
export async function getServerSideProps(context) {
const data = await fetch('https://api.example.com/data');
return {
props: { data: await data.json() }
};
}
export default function Page({ data }) {
return <div>{data.title}</div>;
}
// ✗ WRONG: Attached as property
Page.getServerSideProps = async (context) => { /* ... */ };
// ✗ WRONG: Inside component
function Page() {
export async function getServerSideProps() { /* ... */ }
return <div>...</div>;
}If you need data in a component, fetch it in the page's getServerSideProps and pass it down as props:
// pages/dashboard.tsx
export async function getServerSideProps() {
const userData = await fetchUserData();
const statsData = await fetchStats();
return {
props: {
user: userData,
stats: statsData
}
};
}
export default function Dashboard({ user, stats }) {
return (
<div>
<UserProfile user={user} />
<StatsWidget stats={stats} />
</div>
);
}
// components/UserProfile.tsx
export function UserProfile({ user }) {
// Receives data via props, no getServerSideProps needed
return <div>{user.name}</div>;
}If multiple pages need the same data fetching logic, create reusable utility functions:
// lib/data-fetching.ts
export async function fetchUserData(userId: string) {
const res = await fetch(`https://api.example.com/users/${userId}`);
if (!res.ok) throw new Error('Failed to fetch user');
return res.json();
}
// pages/profile.tsx
import { fetchUserData } from '@/lib/data-fetching';
export async function getServerSideProps(context) {
const { userId } = context.params;
const user = await fetchUserData(userId);
return { props: { user } };
}
// pages/settings.tsx (reuses same function)
import { fetchUserData } from '@/lib/data-fetching';
export async function getServerSideProps(context) {
const userId = context.req.cookies.userId;
const user = await fetchUserData(userId);
return { props: { user } };
}If you're using the App Router (/app directory), replace getServerSideProps with async Server Components:
// app/products/[id]/page.tsx (App Router)
interface Props {
params: { id: string };
}
// Server Component with direct async fetching
export default async function ProductPage({ params }: Props) {
const product = await fetch(
`https://api.example.com/products/${params.id}`,
{ cache: 'no-store' } // Equivalent to getServerSideProps
).then(res => res.json());
return (
<div>
<h1>{product.name}</h1>
<p>{product.description}</p>
</div>
);
}Use cache: 'no-store' in fetch to replicate getServerSideProps behavior (request-time fetching).
If you need dynamic data in a specific component, use client-side fetching with React hooks:
// components/RecentActivity.tsx
'use client';
import { useEffect, useState } from 'react';
export function RecentActivity() {
const [activity, setActivity] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
fetch('/api/activity')
.then(res => res.json())
.then(data => {
setActivity(data);
setLoading(false);
});
}, []);
if (loading) return <div>Loading...</div>;
return <div>{activity.message}</div>;
}This approach works in both Pages Router and App Router for component-specific data.
Ensure you're not mixing Pages Router and App Router patterns in the same route:
# ✗ WRONG: Cannot have both
pages/dashboard.tsx # Pages Router
app/dashboard/page.tsx # App Router (conflicts!)
# ✓ CORRECT: Choose one approach
pages/dashboard.tsx # Pages Router only
# OR
app/dashboard/page.tsx # App Router onlyCheck your project structure and next.config.js to determine which router you're using. If you have both /pages and /app, Next.js prioritizes /app for matching routes.
Next.js enforces the page-level restriction on getServerSideProps because it needs to identify data fetching requirements at build time for proper routing and server-side rendering setup. The function receives a context object with req, res, params, query, and other request-specific data that only makes sense at the route/page level.
When migrating from Pages Router to App Router, note that the new approach provides more granular control—you can fetch data at any component level in the tree, not just at the page level. App Router also introduces better caching strategies with revalidate options and streaming capabilities.
For hybrid scenarios where you need both server-side and client-side data, consider using getServerSideProps for initial critical data (SEO-relevant, above-the-fold) and client-side fetching with SWR or React Query for secondary, interactive data. This approach optimizes both initial page load and subsequent interactivity.
If you're working with incremental migration from Pages to App Router, you can run both routers simultaneously—just ensure routes don't overlap. Use the App Router for new features while gradually migrating existing Pages Router routes.
React Hook useCallback has a missing dependency: 'variable'. Either include it or remove the dependency array react-hooks/exhaustive-deps
React Hook useCallback has a missing dependency
Cannot use private fields in class components without TS support
Cannot use private fields in class components without TS support
Cannot destructure property 'xxx' of 'undefined'
Cannot destructure property of undefined when accessing props
useNavigate() may be used only in the context of a <Router> component.
useNavigate() may be used only in the context of a Router component
Cannot find module or its corresponding type declarations
How to fix "Cannot find module or type declarations" in Vite