ember.js
ember.js copied to clipboard
[Bug] <RouterService>#transitionTo incorrectly re-runs the the model hook when query params do not change
🐞 Describe the Bug
- have queryParams
- configure the query params to
refeshModel: true
- navigate to a child route with the router service's transitionTo
- notice that the parent route's model hook re-runs
🔬 Minimal Reproduction
😕 Actual Behavior
the parent model hook is re-running (in the application route in the repro)
🤔 Expected Behavior
the parent model hook should not run (as with the transitionToRoute behavior)
🌍 Environment
- Ember: - Octane+
- Node.js/npm: - n/a
- OS: - n/a
- Browser: - n/a
I came across a behavior which may be related to this bug. The context is as follows:
parent route -- child route ---- component
The parent route's controller has a queryParam
. The component needs to update that queryParam
and uses this.router.transitionTo({ queryParams: { prop: value }});
to do so. The queryParam
prop is being modified, which is different than this bug report, but the child route model
hook is still being triggered.
To work around the issue I now call this.transitionToRoute({ queryParams: { prop: value }})
on the child route's controller. The model
hook is no longer run again in this case.
I'm running into this issue as well. Seems to be happening when migrating to the new class
syntax.
We actually had this come up. I accidentally use this as a behavior to refresh a route without realizing this was going on until I called it twice... 🤦🏽
This is documented in the transitionTo
behavior but would be nice to not have default queryParam values pop up.
This is one of the aged issues https://github.com/emberjs/ember.js/issues/16349
I think I came across the same issue while migrating to ember 3.24 with native class syntax:
parent route
-- child route
----- component
The component was using the router service to update query params of the child route:
this.router.transitionTo({ queryParams: {} })
Or even simply the route:
this.router.transitionTo(newRoute)
But the parent route model's hook was re-run.
Delegating the update to the child route's controller using transitionToRoute
solved this issue.
We're also running into this issue when refactoring the deprecated this.transitionToRoute
call in Controllers to this.router.transitionTo
.
As this issue causes a lot of extra unnecessary model calls and slows down our app it's a critical issue.
A temporary workaround seems to be returning the previous model state like so:
model(params, transition) {
super.model(...arguments);
// Reuse the previous model state when redirecting to, or redirected back from a child route
if (isRedirectFromOrToChildRoute(transition)) {
return this.modelFor(this.routeName);
}
// Redacted ...
}
// With isRedirectFromOrToChildRoute e.g.
isRedirectFromOrToChildRoute(transition) {
const routeNameFromStripped = transition.from?.name?.replace('.index', ''); // Can be undefined when it's the first page accessed
if (routeNameFromStripped) {
const routeNameToStripped = transition.to.name.replace('.index', '');
const isChildRoute = routeNameFromStripped.startsWith(routeNameToStripped);
const isParentRoute = routeNameToStripped.startsWith(routeNameFromStripped);
const isSameRoute = routeNameFromStripped === routeNameToStripped;
return !isSameRoute && (isChildRoute || isParentRoute);
}
return false;
}
But as it's such a core functionality of routing this seems like a hacky approach ...
I'm experiencing the same issue on ember 4.6.0
I've confirmed that if I remove the refreshModel: true
from the queryParam the parent hook doesn't fire on transition.
Also experiencing this issue on Ember 3.28.11, Ember 4.4.4 and Ember 4.9.2
Having to stick with Controller.transitionToRoute for certain calls to avoid slow page transitions
I have confirmed the router.transitionTo problem still exists with Ember 4.12
This is now actually a problem as transitionToRoute
is removed in ember 5, and I would like to update..
This seems like it may be related to #16349, #20038 and #20512 as well and indeed still occurs in ember 5.