HomeBytesheetsRoadmapsUI TemplatesUI ToolsStack Discussion
5 Topics
Chapter•95 Minutes

State Management, Forms and Client-Side Data

Learn when to use React state, URL state, server state, context, external stores, and client-side data libraries in a Next.js architecture.

Local Component State

Local state should be the default choice when state belongs to one interactive component. Examples include open/closed dropdowns, form input state, tab selection, and temporary UI state.

Do not move every piece of state into Redux or another global store. Global state introduces synchronization and architectural complexity.

Local State
'use client';

import { useState } from 'react';

export default function Accordion() {
  const [open, setOpen] = useState(false);

  return (
    <button onClick={() => setOpen(value => !value)}>
      {open ? 'Close' : 'Open'}
    </button>
  );
}
💡 The open state belongs only to this interactive component, so local state is appropriate.
Key Takeaways
  • Keep local state local.
  • Do not introduce global state without a cross-component requirement.
  • Functional state updates are useful when the next value depends on the previous value.

URL State

Some state should live in the URL rather than React state. Search terms, filters, sorting, pagination, and selected tabs can often be represented as query parameters.

URL state is shareable, bookmarkable, and survives refreshes. This makes it particularly useful for search and catalog pages.

Search URL
/products?search=laptop&sort=price&page=2
💡 The URL represents the current search state and can be shared with another user.
Key Takeaways
  • Use URL parameters for shareable navigation state.
  • URL state improves refresh and bookmarking behavior.
  • Validate and normalize query parameters.

React Context in Next.js

Context is useful for client-side values that need to be shared across a subtree, such as theme preferences or UI state.

Because Context uses client-side React behavior, providers often need to be Client Components. The provider can then wrap only the part of the tree that actually needs the context.

Avoid placing a huge global provider around the entire application if only a small section needs it.

Key Takeaways
  • Context is useful for shared client-side state.
  • Keep providers as narrow as practical.
  • Context is not automatically a replacement for server-side data fetching.

Redux and External Stores

External state libraries can still be useful in Next.js applications, especially when complex client-side state must be shared across many interactive components.

However, distinguish server state from client state. Database records fetched from the server do not necessarily belong in a global Redux store.

Use external stores for genuinely client-owned state such as complex editors, multi-step workflows, offline state, or sophisticated UI interactions.

Key Takeaways
  • Do not automatically put server data into global client state.
  • External stores are best for complex shared client state.
  • Server Components and server-side data fetching can eliminate many client-state requirements.

Client-Side Data Fetching

Client-side fetching is appropriate when data depends heavily on browser interaction, frequent polling, real-time updates, or client-controlled parameters.

Libraries such as SWR or TanStack Query can provide caching, deduplication, retries, refetching, and mutation management.

The correct question is not 'Should I use a data-fetching library?' but 'Where does this data belong and who owns its freshness?'

Key Takeaways
  • Use client fetching when browser-driven updates are important.
  • Server fetching is usually preferable for initial page content.
  • Choose a client data library based on actual state and synchronization requirements.