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
Resets to 0 when you refresh the page
Try refreshing the page - this counter will reset to 0
URL State Counter
Stored in the URL, shareable and bookmarkable
Watch the URL change as you click. Copy the URL and share it - others will see the same count!
LocalStorage Counter
Persists across browser sessions on this device
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
Configure a phone and share your exact selection via URL
Your Configuration
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.