-
-
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
Fix <Route children> #6362
Comments
If the eventual plan is that But either way, seems like a good plan. |
Thanks for the feedback, @bradwestfall :) The reason I like <Route path="/about" children={() => (
<About />
)} />
// or:
<Route path="/about">
<About />
</Route> vs <Route path="/about" render={() => (
<About />
)} /> Plus I'm seeing the community settle more on |
As a rebuttal, I'd prefer to see |
I think it's a good path forward, also the usage of |
@mjackson I often use Class contextType api const Component = class extends React.Component {
contextType = RouterContext;
handler = () => {
this.context.history.push('/users')
}
} or context.unstable_read api const Component = () => {
const { history } = RouterContext.unstable_read();
return <div onClick={() => history.push('/users')}></div>
} |
@TrySound I feel like whether or not we export context is a slightly different discussion that probably deserves its own issue. Please feel free to open another one :) |
I mean this should be considered too since you remove this possibility from |
@TrySound You can always render a <Route children={({ history }) => (
// off you go!
)} /> |
Ah, I get it. So no actual breaking changes in my app. I opened an issue about more ways to access context. |
@mjackson will it be valid to render a Match inside of a Switch? what would the Switch behavior be if the Match object did not actually match the path? |
Switch reads its children's props directly and chooses which one to render. You can actually put anything under a Switch, as long as it has the right props. I wouldn't advise it, but it is possible. So the true behavior of Switch wouldn't change. It might mess with your perceptions of what it does, but that would be up to us to provide better documentation. |
right, my question was does it render the first renderable thing (the Match) regardless of whether the Match actually matches? it kind of breaks the notion of switching since it will always claim the render slot so to speak |
@gnoff I tend to think of |
Oh i don't have one, just thinking we should explicitly scope Switch to Route components then and forbid this use. Just exploring the API. I guess the problem/feature already existed |
Ah re-reading the Switch src I see Match and Route would basically work the same when the a Match matched the route and Match would not be rendered at all if the match failed. So there is no point in using Match inside of Switch but if you did you would get new Route behavior. Seems harmless but maybe worth identifying for people in |
https://greensock.com/react shows a good use case for rendering a route even when it doesn't match the url. See route animation demo. |
I made a PR for this issue. I may have misunderstood the idea, but my take was that we create a |
@PiereDome I didn't review in detail but it seems you've got Match and Route inverted. Route would be updated to remove Then Match would be written to work like Route does today where it always renders and the user can opt to handle match and non-match cases as they wish the smallest delta is probably something like
|
@mattcolman Thank you for mentioning animation and linking me to the animation example on GSAP. I hadn't seen that before. This change won't require you to use a Remind me to include a GSAP example when we ship this... 😅 |
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions. |
I'm a bit surprised this made it to master, as this a pretty major / breaking API change. Should I revive my |
@StringEpsilon Maybe we don't need a separate // using a pseudo api as parameters (has to be defined)
<Route validate={({ location }) => location == "/admin" && isAdmin(user)}>
<AdminPanel />
</Route>``` |
The only thing that made it into master is that we now only render Before: <Route path="/home">
{/* This always rendered, even with the path was not /home, which was a bug */}
<HomePage />
</Route> After: <Route path="/home">
{/* This only renders when the path matches */}
<HomePage />
</Route> |
Additionally, before this commit:
Is identical in behavior to:
That doesn't make any sense to have as an API. We already have |
The reason of code above was strictly explained in the docs. So still I think this behavior change should be introduces as a breaking change and docs should be updated. |
There was a lot of discussion in #5583 about removing the
<Route children>
prop and adding a new prop about when to render. The conversation in that issue stalled, so I'd like to resume it here, but with a completely different proposal.The core issue is that it's not very clear what the difference is between
<Route children>
and<Route render>
. The API doesn't really say anything about when to use one over the other.In contrast to the proposal in #5583 (remove
children
and add a new prop about when to render) I'd like to propose that we just tweak the waychildren
works and get rid ofrender
(eventually). Here's why:Currently,
<Route children>
always renders, which doesn't make any sense. Wanna see something crazy?You might think these routes only render when the URL path is
/about
, but nope. They both will render at any URL. 🙃 This is a huge mistake in the v4 API, and I'd be very surprised if anyone is actually using<Route children>
like this.The reason this API exists is because you're supposed to check the
match
prop to see if the<Route>
matched before rendering anything, e.g.:So now if the URL is
/about
you'll get the<About>
page, otherwise<NotFound>
. That at least makes a little more sense than the previous examples, and hopefully redeems us a little. But it doesn't change the fact that the first examples are just crazy.The vast majority of the time you want to render something only when the route matches the URL, and ignore misses. So we added the
<Route render>
and<Route component>
APIs that will only render something when it matches. These are used much more commonly than<Route children>
in all our docs and examples.The Proposal
It's quite simple, really: The default behavior of
children
should be to only render something when the route matches the URL. We don't need any new API to<Route>
, and we definitely don't want to get rid of thechildren
prop. We just need to fix it.What about misses?
The majority of the time someone wants to handle a "miss", they actually want to render a "not found" page. We actually already have great support for this inside a
<Switch>
:For the rare use case that someone wants to render a standalone
<Route>
that does not match the URL, we already provide thematchPath
function. If we want a component API, we can provide a lower-level component, call it a<Match>
, that will just compute the match and tell you whether or not the path matched:Pros:
<Route children>
is a lot more intuitive<Route children>
would behave the same as<Route render>
, we can eventually remove<Route render>
(less API is almost always a good thing)<Route>
always matches, it will be a lot easier to implement relative<Route>
s and<Link>
s (see RFC: Relative Links and Routes #5127)<Route>
now with your own component, since you have one less render prop to worry aboutCons:
The Plan
<Match>
component and encourage everyone who is usingchildren
to render something when a<Route>
doesn't match a URL (probably a very small % of users) to use a<Match>
instead. Unfortunately, there's no easy way for us to warn users to stop usingchildren
for non-matches.<Route>
only renders something when it matches. I would expect this to break very few apps, but hey, you never know. Also, keep therender
prop around for a while to ease the upgrade.render
prop since it's identical tochildren
now and warn people to just usechildren
instead.Thoughts?
The text was updated successfully, but these errors were encountered: