Dispatch ngrx store action in route resolver

北城余情 提交于 2021-01-27 05:31:30

问题


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.


回答1:


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.
    });
}


来源:https://stackoverflow.com/questions/43982816/dispatch-ngrx-store-action-in-route-resolver

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!