I'm currently have a container (stateful) component which dispatches a select
and a get
action based on a route param (id) in the ngOnInit
method. The point of these actions to have the data and the selected id in my store.
I'm curious would it be correct to dispatch these actions in a resolver?
Thanks for the replies.
My component:
@Component({
selector: 'app-container',
templateUrl: './container.component.html',
styleUrls: ['./container.component.css']
})
export class ContainerComponent implements OnInit, OnDestroy {
private componetDestroyed$ = new Subject();
constructor(private store: Store<fromRoot.State>, private route: ActivatedRoute) { }
ngOnInit() {
this.route.params
.filter(params => params['id'])
.map(params => params['id'])
.takeUntil(this.componetDestroyed$)
.subscribe(id => {
this.store.dispatch(new GetAction(id));
this.store.dispatch(new SelectAction(id));
});
}
ngOnDestroy() {
this.componetDestroyed$.next();
this.componetDestroyed$.unsubscribe();
}
}
My routes:
[{
path: ':id',
component: ContainerComponent
}]
The resolver would be:
@Injectable()
class MyResolver implements Resolve<any> {
constructor(private store: Store<fromRoot.State>) {}
resolve(route: ActivatedRouteSnapshot, state: RouteStateSnapshot) {
let id = route.params['id'];
this.store.dispatch(new SelectAction(id));
this.store.dispatch(new GetAction(id));
return null;
}
And the modified routes:
[{
path: ':id',
component: ContainerComponent,
resolve: {
store: MyResolver
}
}]
And that's why I'm not sure this is correct, becuase the store will always be null
.
There is nothing wrong with the way how you dispatch actions in ngOnInit
based on this.route.params
.
What is important is that the resolvers are data providers for routes. And if you don't provide data then you are using them wrongly.
In you case it sounds more like a canActivate
guard that is responsible to emit actions and allow the route.
Nevertheless you could extend the resolver to selecting data you want.
@Injectable({
providedIn: 'root',
})
export class DataResolver implements Resolve<number> {
constructor(private store: Store) {
}
public resolve(
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot
): Observable<any> {
this.store.dispatch(LoadDataForMyRoute());
return this.store.pipe(
select(dataForMyRoute),
filter(data => !!data), // <- waiting until data is present
take(1), // <- important to add
);
}
}
and in your component you can access it like that instead of this.store.select
.
constructor(
protected readonly store: Store,
protected readonly activatedRoute: ActivatedRoute,
) {}
public ngOnInit(): void {
this.activatedRoute.data.subscribe(data => {
// everything is here.
});
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With