-
-
Notifications
You must be signed in to change notification settings - Fork 10.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
V6: Optional parameters #7285
Comments
We don't plan on supporting them in v6. |
@timdorr Thanks - could you explain a little on how you would achieve it in v6? At the moment I have the below which works but seems less than optimal. Any thoughts?
|
It would be great if this could be described in the migration guide – or if there was at least a hint. So the recommended way of doing "optional" params really is ...
... ? |
@gopeter Yes, or you can do something like this: <Route path="/page/:friendlyName">
<Route path=":sort" element={<Page />} />
<Route path="" element={<Page />} />
</Route> |
Aaaaah, great, thank you very much! 😄 |
@MeiKatz @timdorr my problem with the approach above is that the This is my use case; <Route path="tickets">
<Routes>
<Route path="archive">
<Route path=":ticketId/:content" element={<List />} />
<Route path=":ticketId" element={<List />} />
<Route path="/" element={<List />} />
</Route>
<Route path="view/:ticketId">
<Route path=":content" element={<List />} />
<Route path="/" element={<List />} />
</Route>
<Route path=":ticketId">
<Route path=":content" element={<List />} />
<Route path="/" element={<List />} />
</Route>
<Route path="/" element={<List />} />
</Routes>
</Route> A user starts at Any other suggestions on how to implement this (Route-wise) without having to refactor the complete |
@robbinjanssen Have you thought about using the <Route path="tickets" element={ <TicketsPage /> }>
<Route path=":ticketId" element={ <ShowPage /> } />
<Route path="" element={ <IndexPage /> } />
</Route> const TicketContext = React.createContext( {} );
function TicketsPage() {
const [ tickets, setTickets ] = useState({});
useEffect(() => {
// do some loading stuff
const res = await fetch("/tickets");
const tickets = await res.json();
setTickets( tickets );
}, []);
return (
<Fragment>
<h1>My Tickets</h1>
<TicketContext.Provider value={ tickets }>
<Outlet />
</TicketContext.Provider>
</Fragment>
);
}
function ShowPage() {
const tickets = useContext( TicketContext );
const { ticketId } = useParams();
const ticket = tickets[ ticketId ];
return (
<div>{ JSON.stringify( ticket ) }</div>
);
} |
@MeiKatz not yet, hoped I would not have to refactor that ticket page, but seems like there's no other way. It's a pretty "old" component that requires a lot of work when refactoring. So I wish I could somehow keep the optional parameters :) |
@robbinjanssen Understandable. But I don't think that there is any other way you can solve it. And I also think, that it is a clean way to do it. Also we could think about dropping the whole context stuff and pass the parameters to the |
For now I'll just parse the "raw" params into the bits I need, those URLs are not that complicated fortunately, and i'll put the component on the refactor list. Thanks :) |
Is there anywhere public that we can see the reasoning behind the choice to drop this feature? I appreciate the workarounds and help you've provided above @MeiKatz, but they're still a less ergonomic developer experience (IMO at least). I can't imagine that you'd take that choice without good reason, but it'd be good to know what that was and if it's something that can be overcome? |
Facing a similar issue. I want to open a Modal depending on the optional parameter. The Modal needs to be mounted already in order to show/hide correctly. I don't think using an outlet with immediate mount/unmount will work here. So I'm doing this as a work around. This way I can parse the route params in the HomePage Component, where the Modal is already mounted: <Route path="/" element={<HomePage />}>
<Route path=":activity_id" element={null} />
</Route> |
Dropping v5-style optional parameters is requiring significant code changes to migrate from v5 to v6. Aside from the new v6 optional parameter patterns "seeming" a bit inefficient, it's also requiring architectural changes to the target application to avoid unnecessary component reloads (similar to what @robbinjanssen stated). As a result, it seems there is no clean migration path from v5 to v6 and may roll back to v5 until more time can be invested to pull projects forward to v6. I want to emphasize, the work on react router is valuable and much appreciated. I too wish there was a bit more collaborative discussion on this before such an impactful change. |
I would like to chime in and second that this is a huge change. It means changing the architecture of an application. For our application, this will result in multiple weeks of work. |
same here, our application will need couple of weeks of refactoring because of missing optional parameters :( I was very excited about v6 but looks like v5 is still better choice for our team now :( |
Really appreciate the work on react router. This comment is meant to be feedback, not a complaint, but I'm starting a new project on v5 because of this issue. It's possible I'm just not the target audience of v6 (I'm using react-router in combination with react-navigation for a cross-platform app, so I've got compatibility issues to think about). v6 looks super awesome and I love the approach, I'm just not sure I understand why optional parameters don't fit in the paradigm. |
Hi there, We are using dynamic routing(based on data from the server). The following path was simply perfect for our case.
Returned component decided what to do based on the optional parameters. Is there any way, how to achieve this kind of behaviour with V6? |
I'm a bit surprised to see that support for optional parameters was dropped in v6. This is an extremely useful feature, and its removal has made a v5 to v6 project more challenging. The workarounds people here have suggested are great for smaller apps, but it's not clear why there has to be a workaround in the first place? I'd love to hear the reasoning behind this change. |
its working |
@timdorr any reply that you want to add? |
I will give my take on this because I find it rather unfortunate that in 2021 the most popular Javascript router doesn't support a pattern I've been using successfully for almost 2 decades. As far as I can see from reactions and discussions in this and other issues, the reason optional parameters are not supported in v6 is because they don't work well with the idea of the When you want to use optional parameters, these are (almost) never related to the hierarchy of the page. Thus, it is suggested that you use query params. For example for ordering, filtering, pagination of the inbox you would start using the querystring: However, folks at @remix reference the old PHP days quite a lot, and they might remember that before the nginxes and node servers, people used apache's
Now, I haven't put much thought in how to get the best of both worlds, and I realize that by keeping a nested That's why I think adding an additional component to deal with a part of the pathname that is not related to the hierarchy (optional parameters), might be worth exploring. For example, Something like <QueryPath path={':city/:from/:till/:page'} defaults={{ city: 'all', from: 'any', till: 'any', page: 1 }} /> a seperate hook like Since constructing these URLs is pretty hard it would be great if one can reuse the configuration (the I hope this is somewhat convincing that there are use-cases and I hope it helps moving this discussion further 🙄 . |
Quick Optional Parameter Solution — Following up on prior post. @jrmyio makes some good observations and worth the read. For the record, I love react-router v5. However, rearchitecting for v6 with what seem to be unintuitive code patterns (hacks) that necessitated deep app code/flow changes, simply to get existing value, required too much effort without meaningful new value. After much head banging, hit a hard-stop with v6 and decided to try wouter. Ended up migrating to wouter quickly with very little effort as the wouter GitHub page is straight-forward, making it an easy migration guide to swap out react-router and regain optional parameters. Hopefully there will be more time to spend with react-router v6, but for now wouter is meeting expectations, and is a smaller library. Keeping fingers crossed for optional parameter backward compatibility from v6!! Maybe this issue should be re-opened? |
This doesn't feel like a react-router 6. This feels more like a new router with a new philosophy. |
For those with the problem of pages unmounting and remounting on route change, I found out now that if you put your element on the parent
to this:
It should work as he expects.... I can't say for sure though as this may depend on the implementation for |
This comment has been minimized.
This comment has been minimized.
@timdorr so are we playing a dead bug? :) lot of downvotes, a lot of developers are in pain because you removed optional parameters without explanation or open discussion... |
I didn't remove them personally. Don't be rude and direct your anger at me. I haven't contributed to the code base in some time. |
@timdorr, sorry but you were the one that wrote "We don't plan on supporting them in v6." without any explanation... |
@timdorr Can I try some pull-request for supporting them? in the same direction than my previous comment (it would expand all possibilities) |
another hacky solution if you don t want to unmount your components is to use useSearchParams so your url will look like this |
I agree with the frustrated commenters that this removal should absolutely be documented, since it used to be supported, and since many widely-used routers support and have historically supported optional parameters in a first-class way. Or you could just support them. Thank you! |
Here's a good workaround: https://replit.com/@caub/makeOptionalRoutes#index.js EDIT: I start to understand this decision to not support optional path params, it's more explicit and actually better, I ended up just adding all possible routes in my config (and not using the helper above) |
Not sure how much your bandwidth is, but I think many people would appreciate a pull request for that, and would argue in favor for that functionality. Not supporting optional parameters is counter industry standards and many of us have headaches because of this choice. |
I thought that optional params and dynamic params (ability to match multiple segments as a single param) were the most basic features of any reasonable router library. I was wrong. |
@powelski I wonder whether there's a good reason for this design choice, though. Maybe the idea was that processing route parameters should happen in functional components with their own (sub-) routes, and maybe optional parameters can always be handled in this way. If anyone can drop some knowledge about this project, I would greatly appreciate it! |
@zachsiegel-capsida no idea, but to me it looks like a terrible decision. |
I searched for a way to use the optional path prefix. In my case, it needed to split the routes by locales. import MainContainer from '../MainContainer';
import {Routes, Route} from 'react-router-dom';
import HomePage from '../../pages/Home';
import AboutPage from '../../pages/About';
import NotFoundPage from '../../pages/NotFound';
import {useTranslation} from 'react-i18next';
const Application = () => {
const {i18n} = useTranslation();
const langPathPrefixes = [...i18n.languages, ''];
const langRoutes = langPathPrefixes.map(langPrefix => (
<Route path={`/${langPrefix}`} element={<MainContainer />} key={`react-router-${langPrefix}`}>
<Route index element={<HomePage />} />
<Route path="about" element={<AboutPage />} />
<Route path="*" element={<NotFoundPage />} />
</Route>
));
return <Routes>{langRoutes}</Routes>;
};
export default Application; |
seems more clunky and messy right now ... |
As an OSS maintainer (of a different project) myself I appreciate that when folks are contributing a useful product for free, it's a case of what-you-see-is-what-you-get. In this instance, I think what's missing from the official response is that "We're not supporting optional params in V6 because nested Routes semantically more flexible". The 'Whats new' docs do go into some depth about the changes: https://reactrouter.com/docs/en/v6/upgrading/v5#relative-routes-and-links |
So if I have routes like the following (e.g. the replacement for optional parameters) and just assign the same key prop to both won't react treat them as the same component (retaining state and keeping what it can in the DOM)?
If that's correct then it seems like this is a pretty easy fix. However, I'm not sure enough about react internals to be totally sure what this does and/or how it works with class components. EDIT: Ok, not a super easy fix if you have an optional parameter below a parameter the key depends on but at least it's a fix. Ahh, I now see why @alexiuscrow was suggesting the approach he did. |
I am sorry to say it but v5 is better than v6. Super cool features are gone... like gone!!! and why ??? Instead of adding more and make the old easy to use you guys cut so much of the router..... I mean who does that?! |
For my use case of dynamically generated routes that need an optional parameter, the above solution does not work I do not think. See my use case below. I can't do this nesting trick because the
|
Depends how you can extract the "params" part from With some comments here, this pattern works like a charm for me - also with automatically created routes - performance optimized.
<Routes>
{/* .. other routes .. */}
<Route path={'/office'}>
<Route index element={<PageOffice/>}/>
<Route path={'mails'} element={<PageMails/>}>
<Route path={':mailId'}/>
<Route path={':mailId/*'}/>
</Route>
</Route>
{/* .. other routes .. */}
</Routes> In const params = useParams()
const mailId = params.mailId |
What a complete and total disaster |
I am getting used to v6 . It’s faster but quite has a great refactoring
from v5
You will have to do more studies on how to use v6
The trade off with v6 to v5 is simplicity and speed
Which is a bonus
To be honest v6 is better than v5
More like flexibility vs performance
Routes still can be made more flexible using hooks like useroute() or
creating your own custom hook
V6 is good also for Testing with jest and react-testing-library
Just take your time to understand v6 before complaining to complain
Thanks all
…On Tue, 30 Aug 2022 at 16:00, Daniel Reguero ***@***.***> wrote:
What a complete and total disaster
—
Reply to this email directly, view it on GitHub
<#7285 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/ALRDXFTDH3EHDYOREGCJJRTV3YOZ5ANCNFSM4MRZQFAA>
.
You are receiving this because you were mentioned.Message ID:
***@***.***>
|
@iamunadike faster how? Faster by micro-optimisation measures if anything. Matching routes happens so rarely and is always relatively fast. You won't tell me that you feel any difference. Saying that v6 is better is a joke. |
Kris , give me your technical side by side comparison then ,
Because your opinions makes the people who released v6 look like fools
Give me why or what the micro optimization measures in context are or is ??
…On Tue, 30 Aug 2022 at 17:21, Kris Powelski ***@***.***> wrote:
@iamunadike <https://github.com/iamunadike> faster how? Faster by
micro-optimisation measures if anything. Matching routes happen so rarely
and is always relatively fast. Saying that v6 is better is a joke.
—
Reply to this email directly, view it on GitHub
<#7285 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/ALRDXFS6NYXPGIJO5NREVVDV3YYHPANCNFSM4MRZQFAA>
.
You are receiving this because you were mentioned.Message ID:
***@***.***>
|
It seems like this is the direction a lot of React framework is heading towards. Next.js uses very similar way of routing as the v6. Remix, framework created by the creator of react-router, also has a routing system that they provide that's quite similar. I'm guessing they are using react-router within Remix, so it made a lot of sense for them to go ahead and implement these changes to fit their framework better. As the user base for Next and Remix grows, this type of routing is starting to become the "standard" almost. Web development is heading towards more strictness, and react-router seems to be going into the same direction. Why should Remix-run maintain v5 when their own framework completely moved away from its philosophy of routing? After being salty having to refactor large parts of my code base (you can see my earlier comment on this post on how salty I was), I'm not so salty anymore. You shouldn't be anymore either, since this will simply prepare us for the future. |
@ymoon715 what's not strict about dynamic route segments or nesting? It's pain in the ass, if anything. |
@iamunadike micro-optimisation means irrelevant optimisation. Assuming v6 is any faster (did someone actually check this?), they gave away many convenient features in favor of this irrelevant performance gain? React routing happens on the client side, so we don't even benefit from those micro gains ourselves as app owners. In reality there is zero sense to make routing faster like that, it was already faster than enough before. |
Not only for UI routing, the reason why I'm no longer salty, as the UI adjustments where the least ones for getting all code more future proof. e.g. the OpenApi Spec specifies " With the bit less flexibility, comes a lot of interoperability - and for the cases where you still need to do it otherways, workarounds are always available - but now always as last resort, without having the impact when doing it "correct". It just isn't nice that this team here doesn't communicate their reasonings behind it (or just somewhere hidden in a PR), e.g. I imagine it could have a direct relation to the |
@elbakerino can we leave performance out of this topic? I can't imagine client-side routing system that would have significant impact on performance. You guys need to stop confusing mental comfort with actual optimisation. |
I'm going to create a topic for this over in Discussions and lock the conversation here, as it's strayed a bit from the original point and devolved into venting. We understand that adopting to v6 requires some refactoring (it is a major release, after all!), and that's always something we need to consider carefully when making significant feature changes. I suspect that adding this feature in v6 wouldn't work without breaking changes to the matching algorithm, but I could be wrong. A more targeted and focused discussion would be a good place to work through proposals while considering potential breakage and edge cases. |
I tried adding a trailing
?
to a route using the v6 router, but it didn't seem to work.Are optional parameters supported in v6, or are they coming later?
The text was updated successfully, but these errors were encountered: