1 of 18

Next.js + Data Fetching Methods

Ketan Mayer-Patel

UNC Department of Computer Science

COMP 426: Modern Web Programming (Fall 2026)

Module 3: Next.js

Lecture 13

2 of 18

In the beginning…

  • … there was a protocol.

​

  • Browser, Server, HTTP

3 of 18

HTML and CSS

  • HTML
    • Hierarchically structured content
  • Page load
    • HTTP request for initial HTML
    • Parsed into DOM
    • Linked CSS requested
    • CSS directs rendering
  • Benefits
    • Separation of concerns
    • Common styling across pages
    • Cacheable

4 of 18

It's Alive!

  • JavaScript
    • Client-side programmability
    • Event-driven interactivity
    • Browser execution environment
      • DOM and other WebAPIs

​

  • A02 - Pixel Painter
    • Classic MVC App architecture
    • Client-side only

5 of 18

Go Fetch!

  • Initially via XHR, now fetch()
  • Single Page Apps
    • HTML is interface skeleton
      • Or possibly empty
    • On hydration
      • Event-handlers attached
      • Programmatic UI construction
      • Data loaded (asynchronously)
        • JSON-based web services
        • Third-party APIs
  • Application Backend
    • Co-designed with client-side
    • Intra- and inter-session state
    • Authenticated API access for user-specific information

​

6 of 18

App-burger Helper

  • You could make everything from scratch using nothing but HTML, CSS, and JavaScript
    • Slow, tedious, error prone

​

  • So along the way, we layered on a toolset and libraries as part of a workflow.

7 of 18

TypeScript and Vite

  • Converts many runtime errors to compile time errors
    • Easier to catch and fix
  • Introduces a build process to our workflow
    • Typically develop locally
      • Local development server for testing
    • Package and deploy for production
      • Vercel, for example
  • Vite tool chain
    • Transforms source TypeScript into bundled JavaScript
    • Transpilation, minification, bundling.

8 of 18

React

  • MVC now becomes UI – State
  • HTML now just a shell
  • Everything is now a component
    • React Component Tree
      • Root App component encompasses everything
    • Think of a component as a bundle of related HTML, CSS, and JavaScript
      • Works particularly well with Tailwind
    • Application state distributed within component tree
      • Any state required by multiple components lifted to first common ancestor
  • Hooks to connect with UI event handling and side effects
    • useState
    • useEffect
    • useMemo
  • Highly-optimized client-side rendering
  • A03 NYT Games

​

9 of 18

Next.js – A Complete Framework

  • URL routing
    • Allows application to provide named entry points / views like an MPA
    • While performing like an SPA

​

  • Server-side Rendering
    • Renders as much of the React component tree as it can on server
    • Client-side components rendered on client and integrated on hydration

10 of 18

App Router

  • URL path matched to file path under /app directory
  • Dynamic routing:
    • [slug]
      • Matches a single path component
    • […slug] and [[…slug]]
      • Matches all remaining path components
      • Double bracket version matches optionally
    • Matched values provided to component as params prop
      • Value is a promise for an object with keys for each match
  • page.tsx
    • Request result is rendered React component
      • Often any related subcomponents in same directory
    • Wrapped in layouts nested from root
  • route.ts
    • Request is handled as an API endpoint

11 of 18

Server vs. Client components

  • Next.js assumes a component is a server component
    • If not, must start with "use client" directive.

​

  • Use client components when:
    • Need to set up event handlers
    • Any other browser-only web APIs
    • Client-side hooks (i.e., useState, useEffect)

​

  • Use server components when:
    • Server-side data fetching
      • From database
      • From web service requiring API key or token
    • Accessing information that shouldn't be exposed to client
    • Anything that doesn't require being a client component

​

12 of 18

When to fetch?

html

URL

White Screen

Hydration�Not Interactive

^

First�Contentful�Paint

(FCP)

Server renders HTML

Fetch

JS

js

^

Time To�Interactive�(TTI)

Loading Data�Interactive

SSR + Client Data Fetching�Initial Page Load

Fetch

Data

json

Running�Interactive

json

html

URL

White Screen

^

First�Contentful�Paint

(FCP)

Server renders HTML

Fetch

JS

js

^

Time To�Interactive�(TTI)

Running�Interactive

SSR + Server Data Fetching�Initial Page Load

Fetch

Data

Hydration�Not Interactive

Time

Consider a component that displays a list of classes retrieved from an API endpoint.

As a client component

Initial load has empty list, request to API made by client, and list re-rendered client-side when data arrives.

As a server component

Request to API made by server and list rendered to HTML server-side on initial load.

Discuss pros and cons and submit attendance check

13 of 18

When to fetch?

html

URL

White Screen

Hydration�Not Interactive

^

First�Contentful�Paint

(FCP)

Server renders HTML

Fetch

JS

js

^

Time To�Interactive�(TTI)

Loading Data�Interactive

SSR + Client Data Fetching�Initial Page Load

Fetch

Data

json

Running�Interactive

json

html

URL

White Screen

^

First�Contentful�Paint

(FCP)

Server renders HTML

Fetch

JS

js

^

Time To�Interactive�(TTI)

Running�Interactive

SSR + Server Data Fetching�Initial Page Load

Fetch

Data

Hydration�Not Interactive

Time

Client Data Fetching: Has a faster FCP → Better UX.

Server Data Fetching: Has a worse FCP, but better SEO.

SEO only matters if data incorporated into the page is not specific to the user or user's input.

In most cases, we will prefer to stick with client data fetching unless the SEO boost is very important – we prefer to always prioritize FCP.

​

14 of 18

Anatomy of a client-side component

  • "use client"
  • Path parameters accessed with useParams() hook
  • fetch via useEffect
    • requires then handlers
    • results in updated state -> triggers rerendering

​

​

15 of 18

Anatomy of a server-side component

  • Allowed to be async
    • Means that we can just await the params prop
    • Similarly, can await fetch() and .json() of the response when fetching data server-side

​

​

16 of 18

Issues with client-side fetching

  • Should conditionally render while loading
  • May need to render differently on error
  • Lots of performance issues
    • Race conditions between re-renders

​

​

17 of 18

ReactQuery

  • Solves many problems related to asynchronous state
    • Cache management
    • Request cancellation

​

  • Requires setting up a QueryClientProvider
    • Wraps over the whole application
    • Used to access a singleton QueryClient

​

  • useQuery hook
    • queryKey: Array with key name followed by dependencies
    • queryFn: Function to fetch data (or do anything really) that returns a Promise for data.
    • Returns object with keys for data, error, and isLoading
      • isLoading while Promise not resolved, becomes false when resolved
      • data returned by Promise
      • error object if there is an exception
  • https://go.unc.edu/426f26-Lec13-DelayedReactQuery

​

​

18 of 18

A04 - Pokedex

  • Not quite ready yet, will be in a day or so.