CoachnestCoachnest
Sign InGet Started
Back to course

Next.js 16: The Complete Developer Guide

…
—
Contents
1

What's New in Next.js 16

Reading14mFree
2

Installation, CLI & Your First Project

Reading12mFree
3

Project Structure & Conventions Deep Dive

Reading16m
4

Turbopack — The New Default Bundler

Video18m
5

Configuring TypeScript, ESLint & next.config.ts

Reading14m
6

Chapter 1 — Quiz

Quiz10m
7

App Router Fundamentals

Reading16m
8

Dynamic Routes, Catch-Alls & Type-Safe Params

Reading14m
9

Route Groups & Parallel Routes

Reading16m
10

Intercepting Routes & Modal Patterns

Reading12m
11

Loading, Error & Not-Found UI

Reading12m
12

Chapter 2 — Routing Quiz

Quiz12m
13

Understanding the Server/Client Boundary

Reading18m
14

Choosing When to use "use client"

Reading14m
15

Composing Server & Client Components

Reading14m
16

server-only, client-only & Code Splitting

Reading12m
17

Chapter 3 — Quiz

Quiz10m
18

Fetching Data in Server Components

Reading14m
19

The Next.js 16 Cache Model

Reading16m
20

Revalidation: revalidateTag, revalidatePath & On-Demand

Reading12m
21

Cache Components — Building Reusable Cached Functions

Reading14m
22

Search Params, Cookies & Dynamic APIs

Reading12m
23

Chapter 4 — Quiz

Quiz12m
24

Server Actions From First Principles

Reading16m
25

Forms with useActionState & Progressive Enhancement

Reading14m

Optimistic UI with useOptimistic

Reading12m
27

Validation with Zod + Server Actions

Reading12m
28

Chapter 5 — Quiz

Quiz10m
29

Static vs Dynamic vs Streaming

Reading14m
30

generateStaticParams & Pre-Rendering Dynamic Routes

Reading12m
31

Incremental Static Regeneration (ISR)

Reading12m
32

Partial Prerendering (PPR)

Reading16m
33

Edge Runtime vs Node.js Runtime

Reading12m
34

Rendering Strategies Deep Dive

Video22m
35

Chapter 6 — Quiz

Quiz12m
36

Tailwind CSS v4 with Next.js 16

Reading14m
37

CSS Modules, Global Styles & Scoped CSS

Reading10m
38

next/image — Smart, Fast Images

Reading14m
39

Fonts, Icons & Metadata

Reading12m
40

Chapter 7 — Quiz

Quiz10m
41

Middleware Fundamentals

Reading14m
42

Sessions, JWTs & Cookies

Reading16m
43

Protecting Server Components & Server Actions

Reading12m
44

Chapter 8 — Quiz

Quiz10m
45

Prisma with Next.js — The Production Setup

Reading14m
46

Mutations: Server Actions + Database Writes

Reading12m
47

Route Handlers & REST APIs

Reading12m
48

Chapter 9 — Quiz

Quiz10m
49

Unit & Component Testing with Vitest

Reading12m
50

End-to-End Testing with Playwright

Reading14m
51

Deploying to Vercel

Reading12m
52

Self-Hosting with Docker

Reading14m
53

Production Performance Checklist

Reading12m
54

Final Assessment — Next.js 16 Mastery

Quiz20m
←→navigate lessons
Chapter 5 of 10·Chapter 5 — Server Actions & Forms
Lesson 26 of 54Reading12 min

Optimistic UI with useOptimistic

#Optimistic UI with useOptimistic¶

For lists where the user adds, removes, or edits items, you don't want to wait for the server round-trip before showing the change. useOptimistic lets you render the predicted next state instantly.

Anatomy¶

tsx
32 lines
1"use client";
2import { useOptimistic } from "react";
3import { addTodo } from "./actions";
4
5type Todo = { id: string; text: string; pending?: boolean };
6
7export function TodoList({ initial }: { initial: Todo[] }) {
8  const [optimistic, addOptimistic] = useOptimistic(
9    initial,
10    (state, next: Todo) => [...state, { ...next, pending: true }],
11  );
12
13  async function action(formData: FormData) {
14    const text = formData.get("text")?.toString() ?? "";
15    addOptimistic({ id: crypto.randomUUID(), text });   // instant!
16    await addTodo(text);                                 // confirms or rolls back
17  }
18
19  return (
20    <>
21      <form action={action}>
22        <input name="text" required />
23        <button>Add</button>
24      </form>
25      <ul>
26        {optimistic.map((t) => (
27          <li key={t.id} className={t.pending ? "opacity-50" : ""}>{t.text}</li>
28        ))}
29      </ul>
30    </>
31  );
32}

How It Works¶

  1. 1The user submits → addOptimistic(newTodo) is called → optimistic is the predicted state.
  2. 2React renders the list with the new item immediately.
  3. 3The server action fires. When the action returns + the Server Component re-renders with fresh data, React reconciles the optimistic state with the real state.

If the action fails, the optimistic state is discarded automatically.

Patterns¶

Optimistic Delete¶

tsx
9 lines
1const [optimistic, removeOptimistic] = useOptimistic(
2  items,
3  (state, idToRemove: string) => state.filter((x) => x.id !== idToRemove),
4);
5
6async function onDelete(id: string) {
7  removeOptimistic(id);
8  await deleteItem(id);
9}

Optimistic Update¶

tsx
10 lines
1const [optimistic, updateOptimistic] = useOptimistic(
2  items,
3  (state, patch: { id: string; fields: Partial<Item> }) =>
4    state.map((x) => (x.id === patch.id ? { ...x, ...patch.fields } : x)),
5);
6
7async function rename(id: string, name: string) {
8  updateOptimistic({ id, fields: { name } });
9  await renameItem(id, name);
10}

When to Skip Optimistic UI¶

  • The action is slow but rare (e.g. a yearly subscription purchase) — users expect a moment of waiting.
  • The action has side effects you can't model client-side (charge a card, send an email).
  • The user is supposed to see that work is happening (e.g., uploading a large file with a progress bar).

For everything else — likes, todos, comments, list reorderings — optimistic UI is a UX upgrade with very little code.

Previous

Forms with useActionState & Progressive Enhancement

Next

Validation with Zod + Server Actions

Use ← → arrow keys to navigate between lessons