How to fix getStaticProps can only be used with pages in React
This error occurs when attempting to use getStaticProps in Next.js App Router. The getStaticProps function is exclusive to the Pages Router and cannot be used in the app directory structure.
Quick fix
Fixes getStaticProps can only be used with pages
# Pages Router structure
pages/
index.js
about.js
_app.js
# App Router structure
app/
page.js
about/
page.js
layout.js- Verify your Next.js directory structure
- For App Router: Use Server Components with fetch
- For Pages Router: Ensure proper export location
- Update caching and revalidation strategies
# Pages Router structurepages/index.jsabout.js_app.js# App Router structureapp/page.jsabout/page.jslayout.jsgetStaticProps can only be used with pages
What this error means
This error indicates that you're trying to use the `getStaticProps` data fetching method in a location where it's not supported. In Next.js, `getStaticProps` is a Pages Router feature that was used to fetch data at build time for static generation. With the introduction of the App Router in Next.js 13+, the data fetching paradigm has fundamentally changed. The App Router uses React Server Components by default, which fetch data directly within components rather than using separate data fetching functions like `getStaticProps`. The error most commonly appears when developers try to use `getStaticProps` in the app directory, or when attempting to export it from non-page files like `_app.js`, `_document.js`, or custom error pages in the pages directory.
Typical symptoms
- Build fails with "getStaticProps can only be used with pages" error
- Application won't compile when using getStaticProps in app directory
- Error occurs after migrating from Pages Router to App Router
- Data fetching doesn't work as expected in App Router components
Common causes
- Using getStaticProps in the app directory (App Router) instead of pages directory
- Attempting to export getStaticProps from _app.js, _document.js, or _error.js
- Exporting getStaticProps from a non-page file in the pages directory
- Attaching getStaticProps as a component member instead of a separate export
- Incomplete migration from Pages Router to App Router
How to fix "getStaticProps can only be used with pages"
Check whether you're using the Pages Router (pages directory) or App Router (app directory):
# Pages Router structure
pages/
index.js
about.js
_app.js
# App Router structure
app/
page.js
about/
page.js
layout.jsIf you have an app directory, you're using the App Router where getStaticProps is not supported.
Replace getStaticProps with direct data fetching in an async Server Component:
Before (Pages Router):
// pages/posts.js
export async function getStaticProps() {
const res = await fetch('https://api.example.com/posts');
const posts = await res.json();
return {
props: { posts },
revalidate: 60
};
}
export default function Posts({ posts }) {
return <div>{/* render posts */}</div>;
}After (App Router):
// app/posts/page.tsx
async function getPosts() {
const res = await fetch('https://api.example.com/posts', {
next: { revalidate: 60 } // ISR equivalent
});
return res.json();
}
export default async function Posts() {
const posts = await getPosts();
return <div>{/* render posts */}</div>;
}For static generation, use cache: 'force-cache' (default behavior):
const res = await fetch('https://api.example.com/posts', {
cache: 'force-cache' // Static generation
});If you're intentionally using the Pages Router, make sure getStaticProps is exported from a page file, not from _app.js or other special files:
Correct:
// pages/blog/[slug].js
export async function getStaticProps({ params }) {
// Fetch data
return { props: { data } };
}
export default function BlogPost({ data }) {
return <div>{/* render */}</div>;
}Incorrect:
// pages/_app.js
export async function getStaticProps() { // ❌ Not allowed
return { props: {} };
}Also ensure it's a separate export, not a component member:
// ❌ Wrong
BlogPost.getStaticProps = async () => { };
// ✅ Correct
export async function getStaticProps() { }Map your Pages Router patterns to App Router equivalents:
Static generation with revalidation (ISR):
// Pages Router
export async function getStaticProps() {
return {
props: { data },
revalidate: 3600 // Revalidate every hour
};
}
// App Router equivalent
const res = await fetch('https://api.example.com/data', {
next: { revalidate: 3600 }
});On-demand revalidation:
// Use revalidatePath or revalidateTag
import { revalidatePath } from 'next/cache';
// In a server action or route handler
revalidatePath('/posts');Dynamic rendering (no caching):
const res = await fetch('https://api.example.com/data', {
cache: 'no-store'
});For dynamic routes, replace both getStaticProps and getStaticPaths:
Pages Router:
// pages/posts/[id].js
export async function getStaticPaths() {
return {
paths: [{ params: { id: '1' } }],
fallback: false
};
}
export async function getStaticProps({ params }) {
const post = await fetchPost(params.id);
return { props: { post } };
}App Router:
// app/posts/[id]/page.tsx
export async function generateStaticParams() {
return [{ id: '1' }, { id: '2' }];
}
export default async function Post({ params }: { params: { id: string } }) {
const post = await fetchPost(params.id);
return <div>{/* render post */}</div>;
}Advanced notes
Incremental Migration Strategy:
You can run both Pages Router and App Router simultaneously during migration. Keep existing pages in the pages directory while gradually moving routes to app. The App Router takes precedence for conflicting routes.
Server Component Benefits:
Unlike getStaticProps, Server Components can fetch data at the component level, not just the page level. This enables more granular data fetching and better code organization.
Client Components:
If you need interactivity, mark components with 'use client' and fetch data using useEffect or libraries like SWR/React Query. However, prefer Server Components for initial data loading.
Edge Cases:
- getStaticProps cannot be used in API routes
- Cannot be exported from pages/api/* endpoints
- Must return an object with props, redirect, or notFound
Performance Considerations:
The App Router's fetch API includes automatic request deduplication, meaning multiple components can request the same data without duplicate network calls. This wasn't possible with getStaticProps.
Frequently asked questions
- What does "getStaticProps can only be used with pages" mean?
- This error indicates that you're trying to use the getStaticProps data fetching method in a location where it's not supported. js, getStaticProps is a Pages Router feature that was used to fetch data at build time for static generation. js 13+, the data fetching paradigm has fundamentally changed.
- How do I fix "getStaticProps can only be used with pages"?
- This error occurs when attempting to use getStaticProps in Next.js App Router. The getStaticProps function is exclusive to the Pages Router and cannot be used in the app directory structure.
- What causes "getStaticProps can only be used with pages"?
- Using getStaticProps in the app directory (App Router) instead of pages directory Attempting to export getStaticProps from _app.js, _document.js, or _error.js Exporting getStaticProps from a non-page file in the pages directory
- Is the "getStaticProps can only be used with pages" error serious?
- It is a medium-severity error — more of a blocker than a risk. The steps above resolve it.
Official resources & further reading
- 📚React Official Documentation
- 📖Next.js App Router Migration Guide(Official Docs)
- 📖Data Fetching: getStaticProps(Official Docs)
- 📖App Router Data Fetching(Official Docs)
- 📝