If you've ever jammed with the console cowboys in cyberspace, you've almost certainly run into query strings before. They're the ?
and &
you see appended onto URLs.
They're a fundamental aspect of how the Web works as they allow you to pass state via the URL. Above is an example of a query string you'd see if you searched for ui.dev
on Twitter.
The query portion of this URL has three keys, q
, src
, and f
. q
represents the text we type into Twitter's search bar, src
tells Twitter how we did it (via typing into the search bar), and f
filters the results of the query by "Latest".
What's nice about this is it's sharable. You could copy and paste that URL into your browser right now and it would work. All the data Twitter needs to properly render the UI is right there in the URL.
With all that said, odds are you're not here to learn what query strings are but instead how to use them with React Router. The good news is that if you're already comfortable with React Router, there are just a few small details you need to know.
Let's say we were Twitter and we were building the Route
for the URL above. It would probably look something like this.
<Route path="/search" element={<Results />} />
Notice at this point there's nothing new. We don't account for the query string when we create the Route
. Instead, we get and parse it inside the component that is being rendered when that path matches - in this case, Results
.
Now the question becomes, how do we actually do this? Before we can answer that question, we first need to learn about the URLSearchParams
API.
URLSearchParams
The URLSearchParams
API is built into all browsers (except for IE) and gives you utility methods for dealing with query strings.
When you create a new instance of URLSearchParams
, you pass it a query string and what you get back is on object with a bunch of methods for working with that query string.
Take our Twitter query string for example,
const queryString = "?q=ui.dev&src=typed_query&f=live";const sp = new URLSearchParams(queryString);sp.has("q"); // truesp.get("q"); // ui.devsp.getAll("src"); // ["typed_query"]sp.get("nope"); // nullsp.append("sort", "ascending");sp.toString(); // "?q=ui.dev&src=typed_query&f=live&sort=ascending"sp.set("q", "bytes.dev");sp.toString(); // "?q=bytes.dev&src=typed_query&f=live&sort=ascending"sp.delete("sort");sp.toString(); // "?q=bytes.dev&src=typed_query&f=live"
useSearchParams
As of v6, React Router comes with a custom useSearchParams
Hook which is a small wrapper over the browser's URLSearchParams
API.
useSearchParams
returns an array with the first element being an instance of URLSearchParams
(with all the properties we saw above) and the second element being a way to update the query string.
Going back to our example, here's how we would get the values from our query string using useSearchParams
.
import { useSearchParams } from 'react-router-dom'const Results = () => {const [searchParams, setSearchParams] = useSearchParams();const q = searchParams.get('q')const src = searchParams.get('src')const f = searchParams.get('f')return (...)}
Then if we needed to update the query string, we could use setSearchParams
, passing it an object whose key/value pair will be added to the url as &key=value
.
import { useSearchParams } from 'react-router-dom'const Results = () => {const [searchParams, setSearchParams] = useSearchParams();const q = searchParams.get('q')const src = searchParams.get('src')const f = searchParams.get('f')const updateOrder = (sort) => {setSearchParams({ sort })}return (...)}
Before you leave
I know, "another newsletter pitch" - but hear me out. Most JavaScript newsletters are terrible. When's the last time you actually looked forward to getting one? Even worse, when's the last time you actually read one rather than just skim it?
We wanted to change that, which is why we created Bytes. The goal was to create a JavaScript newsletter that was both educational and entertaining. 101,879 subscribers and an almost 50% weekly open rate later, it looks like we did it.
Delivered to 101,879 developers every Monday

Sdu
@sduduzo_g
This is the first ever newsletter that I open a music playlist for and maximize my browser window just to read it in peace. Kudos to @uidotdev for great weekly content.

Brandon Bayer
@flybayer
The Bytes newsletter is a work of art! It's the only dev newsletter I'm subscribed too. They somehow take semi boring stuff and infuse it with just the right amount of comedy to make you chuckle.

John Hawley
@johnhawly
Bytes has been my favorite newsletter since its inception. It's my favorite thing I look forward to on Mondays. Goes great with a hot cup of coffee!

Garrett Green
@garrettgreen
I subscribe to A LOT of dev (especially JS/TS/Node) newsletters and Bytes by @uidotdev is always such a welcomed, enjoyable change of pace to most (funny, lighthearted, etc) but still comprehensive/useful.

Muhammad
@mhashim6_
Literally the only newsletter I’m waiting for every week.

Grayson Hicks
@graysonhicks
Bytes is the developer newsletter I most look forward to each week. Great balance of content and context! Thanks @uidotdev.

Mitchell Wright
@mitchellbwright
I know I've said it before, but @tylermcginnis doesn't miss with the Bytes email. If you're a developer, you really need to subscribe

Ali Spittel
@aspittel
Can I just say that I giggle every time I get the @uidotdev email each week? You should definitely subscribe.

Chris Finn
@thefinnomenon
Every JavaScript programmer should be subscribed to the newsletter from @uidotdev. Not only do they manage to succinctly cover the hot news in the JavaScript world for the week but it they manage to add a refreshing humor to it all.