typescriptintermediate
Infinite Scroll with Server Actions
Implement infinite scroll using server actions with cursor-based pagination.
typescriptPress ⌘/Ctrl + Shift + C to copy
// app/feed/actions.ts
'use server';
interface Post {
id: string;
title: string;
excerpt: string;
createdAt: string;
}
interface FeedResult {
posts: Post[];
nextCursor: string | null;
}
export async function loadMorePosts(cursor?: string): Promise<FeedResult> {
const params = new URLSearchParams({ limit: '10' });
if (cursor) params.set('cursor', cursor);
const res = await fetch(`https://api.example.com/posts?${params}`);
const data = await res.json();
return {
posts: data.posts,
nextCursor: data.nextCursor,
};
}
// app/feed/InfiniteFeed.tsx
'use client';
import { useEffect, useRef, useState, useCallback } from 'react';
import { loadMorePosts } from './actions';
interface Post {
id: string;
title: string;
excerpt: string;
createdAt: string;
}
export function InfiniteFeed({ initialPosts, initialCursor }: {
initialPosts: Post[];
initialCursor: string | null;
}) {
const [posts, setPosts] = useState(initialPosts);
const [cursor, setCursor] = useState(initialCursor);
const [loading, setLoading] = useState(false);
const loaderRef = useRef<HTMLDivElement>(null);
const loadMore = useCallback(async () => {
if (loading || !cursor) return;
setLoading(true);
const result = await loadMorePosts(cursor);
setPosts((prev) => [...prev, ...result.posts]);
setCursor(result.nextCursor);
setLoading(false);
}, [cursor, loading]);
useEffect(() => {
const observer = new IntersectionObserver(
(entries) => {
if (entries[0].isIntersecting) loadMore();
},
{ threshold: 0.1 }
);
if (loaderRef.current) observer.observe(loaderRef.current);
return () => observer.disconnect();
}, [loadMore]);
return (
<div>
{posts.map((post) => (
<article key={post.id} className="p-4 border-b">
<h2>{post.title}</h2>
<p>{post.excerpt}</p>
</article>
))}
<div ref={loaderRef} className="py-8 text-center">
{loading && <span>Loading...</span>}
{!cursor && <span>No more posts</span>}
</div>
</div>
);
}Use Cases
- social feeds
- product listings
- blog archives
Tags
Related Snippets
Similar patterns you can reuse in the same workflow.
typescriptintermediate
Server Action with Form Validation
Next.js Server Action handling form submissions with validation, error messages, and redirect on success.
Best for: Blog post creation
#server-actions#forms
typescriptintermediate
Next.js Server Actions with Forms
Use Server Actions for form handling with validation, optimistic updates, and error handling.
Best for: Form submissions without API routes
#nextjs#server-actions
typescriptbeginner
Loading UI with Skeleton Screens
Create loading.tsx skeleton screens for instant navigation feedback with Next.js App Router.
Best for: Route transition loading states
#nextjs#loading
typescriptbeginner
Custom Not Found Page
Create a custom not-found.tsx with search suggestions, popular links, and a return home button.
Best for: Custom 404 error pages
#nextjs#error