Client State vs URL State vs LocalStorage: The Complete Guide

January 2025 · Derick Zr

When building React apps, you have three main options for storing state: React state, URL parameters, and localStorage. Each serves different purposes, and choosing the wrong one creates problems.

Most developers default to React state for everything, but that's a mistake. Here's when to use each one, with interactive examples you can play with.

The Three Types of State

1. Client State (React useState)

  • Lives only in memory while your component is mounted
  • Resets when you refresh the page
  • Perfect for: UI interactions, temporary form data, modal states

2. URL State (Query Parameters)

  • Lives in the browser's address bar
  • Shareable - send the URL to someone else and they see the same state
  • Perfect for: filters, search queries, configuration that should be bookmarkable

3. LocalStorage State

  • Persists across browser sessions on the same device
  • Not shareable - only visible to the current user on their device
  • Perfect for: user preferences, theme settings, draft content

Interactive Examples

Try these demos to see the differences in action:

Example 1: Simple Counter

This counter demonstrates all three approaches. Notice how each behaves differently when you refresh the page or copy the URL.

React State Counter

React State

Resets to 0 when you refresh the page

0

Try refreshing the page - this counter will reset to 0

URL State Counter

URL State

Stored in the URL, shareable and bookmarkable

0

Watch the URL change as you click. Copy the URL and share it - others will see the same count!

LocalStorage Counter

LocalStorage

Persists across browser sessions on this device

0

Close the browser and come back - this counter will remember its value

Key Insights:

  • React State: Fast and simple, but lost on refresh
  • URL State: Shareable and bookmarkable, but updates the browser history
  • LocalStorage: Persists across sessions, but can't be shared

Example 2: Phone Options

On a product page, people pick the specs they want and can share the exact configuration if they want.

Phone Options

URL State

Configure a phone and share your exact selection via URL

Your Configuration

Brand:iPhone
Model:15
Color:Natural Titanium
Storage:128GB

Total:$799

Try this: Configure your ideal phone, then copy the URL and open it in a new tab. Your exact configuration will be preserved! This is perfect for e-commerce where customers want to share their product selections.

Why URL State Wins Here:

  • Customer can share their exact configuration via URL
  • Bookmarkable for later purchase
  • Works across devices if they send themselves the link
  • SEO-friendly if you have different pricing per configuration

Decision Framework

Here's how to choose:

Use React State When:

  • Temporary UI state (modals, dropdowns, form inputs)
  • State only matters while user is actively interacting
  • Performance is critical (no serialization overhead)

Avoid when:

  • You need state to survive page refresh
  • Users might want to bookmark or share the state

Use URL State When:

  • State should be shareable via URL
  • State should be bookmarkable
  • Filters, search queries, or configurations
  • SEO matters for different state combinations

Avoid when:

  • State is personal/private
  • State is complex objects (keep URLs clean)

Use LocalStorage When:

  • User preferences that should persist
  • Draft content or "work in progress" data
  • Theme settings, language preferences
  • Shopping cart contents (until checkout)

Avoid when:

  • State needs to be shared between users
  • State is critical (localStorage can be cleared)

Implementation Patterns

URL State Pattern

const [filters, setFilters] = useUrlState({
  category: 'all',
  priceRange: '0-100'
})
 
// Automatically syncs with ?category=electronics&priceRange=50-200

LocalStorage Pattern

const [theme, setTheme] = useLocalStorage('theme', 'light')
 
// Persists across browser sessions

When to Combine Them

Sometimes you need multiple types:

// URL for shareable filters
const [filters, setFilters] = useUrlState({ category: 'all' })
 
// LocalStorage for user preferences  
const [viewMode, setViewMode] = useLocalStorage('viewMode', 'grid')
 
// React state for UI interactions
const [isModalOpen, setIsModalOpen] = useState(false)

Common Mistakes

Putting everything in React state

// Wrong: Lost on refresh, can't be shared
const [productConfig, setProductConfig] = useState({
  color: 'red',
  size: 'large',
  model: 'pro'
})

Putting UI state in URL

// Wrong: Clutters URL, not bookmarkable in meaningful way
const [isModalOpen, setIsModalOpen] = useUrlState('modalOpen', false)

Putting personal preferences in URL

// Wrong: Not personal, gets shared when URL is copied
const [darkMode, setDarkMode] = useUrlState('darkMode', false)

Key Takeaways

  • React State: Fast, temporary, component-scoped
  • URL State: Shareable, bookmarkable, SEO-friendly
  • LocalStorage: Personal, persistent, device-scoped

The magic happens when you use the right tool for the right job. Your users get better experiences, your code stays cleaner, and your app behavior becomes predictable.

Most importantly: start with React state, then promote to URL or localStorage only when you need the specific benefits they provide.

Client State vs URL State vs LocalStorage: The Complete Guide