Hey Dev.to community!
I recently added URL state management to my Spotify-inspired music app, Moodify, and I’m blown away by how simple and powerful it is. If you’ve ever wanted your app’s state to be shareable, bookmarkable, and stateless without extra libraries, let me show you why URL state management is a game-changer. Let’s dive in with a quick example from my project!, but first.
✨Why URL State Management is Wonderful?
Imagine: you’re using a music app, and you filter songs by a “Happy” mood. You want to share that exact view with a friend. Without URL state, you’d need to manually tell them to select “Happy” after opening the app. But with URL state management, you can share a link like https://moodify-drab.vercel.app/?mood=Happy, and—bam!, they land on the same view instantly. Here’s why it’s awesome:
🔹 Shareable Links: Users can copy-paste URLs to share exact app states.
🔹 Bookmarkable: Refresh the page, and the state persists & no local state needed.
🔹 Stateless: Reduces reliance on Context or local state, minimizing re-renders.
I implemented this in Moodify using useSearchParams
from react-router-dom,
and the result is magical. Let’s see it in action!
✏️// MoodCategories.tsx (Before)
const MoodCategories = ({ moods }) => {
const { selectedMood, setSelectedMood } = useMoodify();
return (
<div>
{moods.map((mood) => (
<button
key={mood}
onClick={() => setSelectedMood(mood)}
className={selectedMood === mood ? 'active' : ''}
>
{mood}
</button>
))}
</div>
);
};
🔗 URL: https://moodify-drab.vercel.app
Problem: Clicking “Happy” updated selectedMood in Context, but the URL stayed the same. Sharing the link wouldn’t preserve the “Happy” filter, and refreshing the page reset it to “All”.
🌐 URL State Management with useSearchParams
I refactored Moodify to use useSearchParams to store the selected mood in the URL. The state now lives in the the query param ?mood=
, making it shareable and persistent. Here’s the updated flow:
Step 1: Read and Write URL State in Home.tsx
I used useSearchParams to manage the mood query param and sync it with MoodifyProvider.
✏️// Home.tsx
import { useSearchParams } from 'react-router-dom';
import { useMoodify } from '../hooks/useMoodify';
import { useEffect } from 'react';
import MoodCategories from '../component/MoodCategories';
const Home = () => {
const { moods, setMood, thumbnailSongs } = useMoodify();
const [searchParams, setSearchParams] = useSearchParams();
const currentMood = (searchParams.get('mood') as Categories) || 'All';
const HandleMoodSelect = (newMood) => {
setSearchParams({ mood: newMood });
};
useEffect(() => {
setMood(currentMood);
}, [setMood, currentMood]);
return (
<div>
<MoodCategories
moods={moods}
currentMood={currentMood}
onMoodSelect={HandleMoodSelect}
/>
...
</div>
);
};
Step 2: Update MoodCategories to Use URL State
I passed the URL-derived currentMood
and HandleMoodSelect
to MoodCategories
as props, removing the dependency on Context for category selection.
✏️// MoodCategories.tsx
const MoodCategories = ({ moods, currentMood, onMoodSelect }) => {
return (
<div className="flex gap-2">
{moods.map((mood) => (
<button
key={mood}
onClick={() => onMoodSelect(mood)}
className={`border-1 rounded-full ${
currentMood === mood ? 'bg-green-500 text-white' : 'bg-gray-200'
}`}
>
{mood}
</button>
))}
</div>
);
};
🔗 URL Before: https://moodify-drab.vercel.app
🔗 URL After: https://moodify-drab.vercel.app/?mood=Happy
🧩 Result: Clicking “Happy” updates the URL to ?mood=Happy. Share that link, and anyone can open the app with “Happy” songs pre-filtered. Refresh the page! it still works!
🎉 Bonus: Handling Invalid Moods
What if someone types ?mood=horror
(not a valid mood)? I added validation to default to “All” and show a toast notification:
✏️// Home.tsx (Validation)
const urlMood = searchParams.get('mood') as Categories;
const currentMood = moods.includes(urlMood) ? urlMood : 'All';
useEffect(() => {
if (urlMood && !moods.includes(urlMood)) {
notify('Invalid category, defaulting to All');
setSearchParams({ mood: 'All' });
}
setMood(currentMood);
}, [urlMood, moods, setMood, notify, setSearchParams]);
🔗 Complete Code: Github
🔄 Finally!
Url state management made Moodify feel more professional and user-friendly. It’s a small change with a big impact—your users will love being able to share and bookmark their app state. Plus, it reduces Context usage, which means fewer unnecessary re-renders.
Top comments (3)
Nice very great explanation, I also tell my friends to don't underestimate power of urls, they're great store managers
I use tanstack router for routing and url management.
Thanks for the kind words! I’ve heard TanStack Router is a big deal right now. It’s definitely gaining traction as an industry trend. I’ll give it a shot for my next project; appreciate you mentioning it! Have you found any standout features in TanStack that you’d recommend?
Yupp, so many great features
It's file based routing is just top notch, with that you don't have to manually write same code for all routes, making nested routing is so easy with file based routing, plus it's great features like caching of routes and load routes is great,
Also supports loader and actions just like react router Dom, and also supports asynchronous data loading ( loose implementing of tanstack query, but I prefer using tanstack query for any asynchronous data fetch as it's great ),
It has also same features like suspense, transition, error compos, pending compos like react router Dom
And same search params like it but with so many great features + it's totally typesafe even in search params, I know you may think that it's just a string, what's need of type safety but believe me when you come to understand search params from tanstack router a whole new world will open for you
Note : I don't know it's mentioned good or not but still saying, I'm new to this community ( I guess 1.25 years ) and just completed react few months back and learnt many popular libs like react router Dom, redux, zustand, tanstack query, react hook form and so on and currently making a standalone project Pocketeer, personal finance app and which is totally built on tanstack suite like tanstack query for data fetching, tanstack router for routing, tanstack store for state management ( everyone should give a try to this manager, it's one of best state management lib I found, this small bird is huge eagle ), tanstack table for data grid ( ahh man, no words for this, definitely give this a try when you want data table, it comes with so many great features and is total customizable ) and tanstack form for forms ( currently on the way ) and learning totally from their documentation ( Note : their documentation may feel overwhelming and rough if you never tried learning from docs just like me but take time, don't rush )
P.S. : I didn't started to learn after it became popular or great, I just learnt tanstack query from my tutor Jonas Schemdmann , and after learning it, I came to thier official site and found that they also provide many other things and at that time I was gonna start my project so I thought why not just use it directly here, lesrn from thier docs, direct implement on project, and after giving time and made project ( still in development ), I can gurrenteed say that learning TanStack suite was totally worth it. In future in any company I place, I've enough reason to at least ask my manager to implement it using TanStack suite where needed.