-
-
Notifications
You must be signed in to change notification settings - Fork 2k
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
Router Store does not wait for deactivate guards to finish #816
Comments
This is by design. Router store emits the action when navigation starts before guards and resolvers have run, giving you an opportunity to stop navigation before running those unnecessarily. |
OK for the action. |
Well, maybe I misunderstood what router-store is all about. IMHO ngrx/router-store should help you move the angular router state into the ngrx/store so normally you would think that they are in sync. Your application is using the app state as the @bbaia I was thinking the same. |
Maybe @vsavkin has an opinion on this :) |
Not sure why this would be as it is 'by design', as soon as we add guards to our routes it defeats the whole purpose of having it. State is already updated with the new route snapshot but the app is not, so one cannot reliably use it. I would rather see this improved, than each of us implementing its own solution or a different lib. |
@adrianfaciu see https://stackblitz.com/edit/ngrx-router-reducer-can-deactivate?file=app%2Fservices%2Frouter-store-extension.service.ts it's hacky but might be of some use to you. |
I have similar problem, in first view I am updating query params and has link to second view. When user navigate to second view, canActivate guard may prevent it and route is not changed, but router store has been changed. Demo: |
@mkurcius hmm... your stackblitz link doesn't seem to work. |
I just check it and it works |
@mkurcius odd now the link works for me... maybe some glitch/delay in their system. |
Ok, but how? Is there a way to intercept |
Of course there is, but the state still doesn't get updated and keeps showing the cancelled one. |
You can always create an "ugly" meta-reducer that runs normal reducer first and then itself. It can remember previous router state and update it with every Note that ngrx/router reducer updates router state even with This solution works, however I don't like it. I think that ngrx/router should take care of routing cancels. |
Running into this issue as well and its very frustrating as it seems to go completely against what would be expected. This meta-reducer seems to work for correcting the state as @jamOne- suggested: export function fixRouterStoreCancel(reducer: ActionReducer<AppState>): ActionReducer<AppState> {
let preCancelState: RouterStateUrl;
return function (state: AppState, action: any): AppState {
let currentAction = action;
if (state && state.router && action.type === ROUTER_NAVIGATION) {
preCancelState = state.router.state;
}
if (action.type === ROUTER_CANCEL || action.type === ROUTER_ERROR) {
currentAction = {
...action,
payload: {
...action.payload,
routerState: preCancelState
}
}
}
return reducer(state, currentAction);
}
} However, I'm still having issues with ROUTER_NAVIGATION updating the store and calling effects before my CanDeactivate guard ends which is causing functions to be called that should only be called if the component is deactivated. It seems like ngrx should be taking care of this kind of thing internally. How can I tell if ROUTER_NAVIGATION is waiting for a guard to finish (confirm dialog in my case) to see if it should run the effect or not? |
I'm struggling with this as well. Needing to implement an inline hack to accomplish this rather than relying on ngrx to wait for the guard to reject the route. |
I ended up combining my effect w/ the NavigationEnd event to make sure it doesn't fire on the initial ROUTER_NAVIGATION that fires before the ROUTER_CANCEL. This kind of works except that it misses the initial loading of the page where I also wanted the effect to call, so I had to create a workaround there. All of this feels pretty hack-ish. @Effect({ dispatch: false })
onNavigateBase$ = this._actions$.pipe(
ofType(ROUTER_NAVIGATION),
combineLatest(this._router.events),
// make sure we don't process this until route guards have completed
filter(([action, routerEvent]) => routerEvent instanceof NavigationEnd),
withLatestFrom(this._store.select(s => s)),
tap(([[action], state]: [[RouterNavigationAction<RouterStateUrl>, RouterEvent], AppState]) => {
const params = action.payload.routerState.params;
const routerRegionCode = getRegionCode(params.regionCode);
if (routerRegionCode !== state.userState.regionCode) {
this._store.dispatch(new SetRegionAction(routerRegionCode));
}
const routerJobPhase = getJobPhase(params.jobPhase);
if (routerJobPhase !== state.userState.jobPhase) {
this._store.dispatch(new SetJobPhaseAction(routerJobPhase));
}
})
); |
@brandonroberts If I'm correct this issue can be closed, fixed via #1267 |
Thanks @dummdidumm |
The problem is now managed with this native feature : https://ngrx.io/guide/router-store/configuration#navigation-action-timing 🚀 |
I'm submitting a...
What is the current behavior?
The router state is updated immediately when you start a new router navigation.
Expected behavior:
The router state should be updated when navigation ends, maybe?! or at least wait for all your guards that delay or stop your navigation and check the result.
Minimal reproduction of the problem with instructions:
Comp2
Comp1
The text was updated successfully, but these errors were encountered: