history
history copied to clipboard
Query parameter questions
Hi maintainers!
To start, thanks so much for creating and maintaining this awesome library, as well as React Router. I've been using them pretty much daily for years now, and I love 'em!
One of the things that I love about history
is that it is unopinionated when it comes to query strings. I think it is especially appropriate a low-level library like this to remain as flexible as possible, and keeping the built-in query param API to strings is the best way to do that, I think.
For applications with more advanced query param needs, however, managing those params with strings isn't the most scaleable option. Unfortunately, the low-level string-based query param API bubbles all of the way up through to React Router, and there's little guidance on the best solution to moving toward an object-centered model for managing query params. The React Router docs (which are awesome overall, btw) only has a relatively simple read-only example for query params.
Some applications have additional concerns that aren't covered in any docs (that I can find), such as dynamically updating query parameters as the user interacts with the app, merging query params, and so on. This is a common-enough use case that I think the community would benefit from some more guidance from this team.
I've seen a bunch of React apps over the past few years, and I nearly always see hacky, ad hoc solutions for managing query params, and the developers working on those apps are never quite happy with what they've come up with. This is no fault of their own; it's a tough problem to solve!
I do not believe that history
nor React Router should or could completely solve this out-of-the-box, but I think providing some guidance to the community could be valuable, which is why I'm opening this issue.
I have a few specific questions for you if you have time:
-
Is there an official opinion on the best way to manage query params as objects? A few months ago there was a suggestion given to wrap history and overwrite some of the methods. This is compatible with React Router given that
<Router/>
lets you pass in your own history methods. Is that the recommended approach? Are there any other suggestions you would give, or is this the best way to support query params overall, in your opinion? -
Do you think it would make sense to add docs to both history and React Router that answer # 1 in more detail? I'd be happy to make a draft of those docs!
-
Do you think it would be appropriate to add some options to
history
that, when passed, "enable" the parsing/stringifying of query param objects? The API would remain as it is today until you pass your ownstringify
/parse
methods. The excellentqhistory
is one example lib that introduces this in a way that I think might make sense for this core library. Imo the functionality people need is well-defined and something that could be in the core lib (CRUD'ing query params as objects); all of the uncertainty comes from the parsing/stringifying algorithms.
One of the reasons I'm opening this issue is that I recently abstracted out the query param solution I've been using into a standalone lib. It works similarly to qhistory in that it wraps the history methods. However, the React Router types don't support custom histories/locations, so I went over to DefinitelyTyped to update them. But then I realized...maybe I've gone about this all wrong and I'm misusing React Router/history? I'm not really sure if the solution is any good or not!
I'd love to hear the team's thoughts on this. And thanks a ton for taking the time out of your busy days to read this super long issue! 🙏
update: it looks like React Router v6's Router
component will remove the history
prop. What are the implications of this change for libs like qhistory
/ query-history
? Will it be much more difficult to use this approach when managing query params?
@jamesplease FWIW, I'd also like to see some further discussion this area!
I've recently run into difficulties while trying to understand how to effectively use history together with query params. Despite my best efforts at trying to get things to play nicely I still haven't been able get come up with a non-hacky solution for handling query parameters in such a way that I don't trigger remounting of components needlessly.
The specific scenario I've come up with, that I'm sure other people must also struggle with is the case of applications that use URL query parameters to control things like tables and lists (think filtering, ordering, etc.).
hmm...What to do about this? We want to have the filters reflected in our URLs (/myApp/workList?isRunning=false&isFailed=true
), and we want to track the history of those changes (the back button works), but we certainly don't want to remount large portions of our application because of a history.push()
his side-effects all the way up the <Route>
and beyond.
Heck, maybe there already is a solution to this scenario, but it isn't obvious (to me, anyways)..two cents.