https://blog.nrwl.io/managing-state-in-angular-applications-22b75ef5625f
(記事の要約)
(個人的な)
BehaviorSubject
ComponentA
ComponentB
GET /users
PUT /users/123
DELETE /users/456
@Injectable()
export class UserHttpService {
private _user: BehaviorSubject<User>;
private user: Observable<User>;
constructor(private http: HttpClient) { }
fetchUser(): Observable<User> {
return this.http.get<User>('/api/user')
.switchMap((user: User) => {
if (this._user) {
this._user.next(user);
return this.user;
} else {
this._user = new BehaviorSubject(user);
this.user = this._user.asObservable();
return this.user;
}
});
}
getUser(): Observable<User> {
return this.user || this.fetchUser();
}
updateUser(user: Partial<User>) {
return this.http.put('/api/corporate', user)
.do(() => {
if (this._user) {
const current = this._user.getValue();
this._user.next({ ...current, ...user });
}
});
}
}
データをキャッシュしマルチキャストする
BehaviorSubject
外側からいじられたくないのでObservableに変換
HTTPから得たデータの後続にswitchMapでBehaviorSubjectをくっつけて更新が流れてくるようにする
既にfetch済みならそれでいいですというユースケースに対応
getValue()をつかって楽観的更新
// inputにidを入力するとURLが/foo?id=123のように変わり、
// そのidのデータを取得して表示するコンポーネント
@Component({
template: `
<input type="text" #input placeholder="enter id"/>
<button (click)="onClick(input.value)">submit</button>
<p>{{result$ | async}}<p>`
})
export class FooComponent implements OnInit {
result$: Observable<string>;
constructor(
private route: ActivatedRoute,
private router: Router,
private service: FooService,
) { }
ngOnInit() {
// URLを状態のソースとして、変更を監視する
this.result$ = this.route.queryParams.switchMap((params: Params) =>
this.service.getFoo(params['id'])
);
}
onClick(id: string) {
// 状態の変更はURLに対して行う
this.router.navigateByUrl(`/foo?id=${id}`);
}
}
Persistent state
Server state
Transient client state
Cookie, LocalStorage, ..
Client state
URL state
Service
Component
同期
同期
同期
リソースを管理してSubjectで公開する
ActivatedRoute, Routerを使ってURLに状態を反映・監視
Local UI state
リソースと画面の状態からあれこれ計算する
ドメインロジック
表示に専念する
難しいことは下のServiceに任せる
Persistent state
Server state
Transient client state
Cookie, LocalStorage, ..
Client state
URL state
Service
Component
同期
同期
同期
Local UI state
Presentation
Domain logic
Resource management