私はngxs
の実験を始めましたが、これまでの読み取りから、データを永続化して読み取るためにAPIにコールバックする場所について100%明確ではありません(私が見たすべての例はそれをしない、またはいくつかのモックを使用する)。
例えば。アイテムのリストを保持する状態を作成しました。アイテムを追加するときは、「AddItem」アクションをストアにディスパッチし、そこで新しいアイテムを状態に追加します。これはすべて正常に動作します-質問は、アイテムをサーバーにPOSTする呼び出しをプラグインする適切な場所はどこですか?
アクションの実装で、つまりストアのアイテムリストを更新する直前にAPIを呼び出す必要があります。
または、Angularコンポーネント(サービス経由)でAPIを呼び出し、応答を受け取ったときに 'アイテムの追加'アクションをディスパッチしますか?
私はこの分野にはまったく慣れていないので、これらのアプローチのガイダンスや賛否両論は素晴らしいでしょう。
最適な場所は、アクションハンドラーです。
import { HttpClient } from '@angular/common/http';
import { State, Action, StateContext } from '@ngxs/store';
import { tap, catchError } from 'rxjs/operators';
//
// todo-list.actions.ts
//
export class AddTodo {
static readonly type = '[TodoList] AddTodo';
constructor(public todo: Todo) {}
}
//
// todo-list.state.ts
//
export interface Todo {
id: string;
name: string;
complete: boolean;
}
export interface TodoListModel {
todolist: Todo[];
}
@State<TodoListModel>({
name: 'todolist',
defaults: {
todolist: []
}
})
export class TodoListState {
constructor(private http: HttpClient) {}
@Action(AddTodo)
feedAnimals(ctx: StateContext<TodoListModel>, action: AddTodo) {
// ngxs will subscribe to the post observable for you if you return it from the action
return this.http.post('/api/todo-list').pipe(
// we use a tap here, since mutating the state is a side effect
tap(newTodo) => {
const state = ctx.getState();
ctx.setState({
...state,
todolist: [ ...state.todolist, newTodo ]
});
}),
// if the post goes sideways we need to handle it
catchError(error => window.alert('could not add todo')),
);
}
}
上記の例では、APIを返すための明示的なアクションはありません。AddTodo
アクションレスポンスに基づいて状態を変更します。
必要に応じて、より明確にするために3つのアクションに分割できます。
AddTodo
、AddTodoComplete
およびAddTodoFailure
この場合、http投稿から新しいイベントをディスパッチする必要があります。
エフェクトをストアから分離する場合は、基本状態クラスを定義できます。
@State<Customer>( {
name: 'customer'
})
export class CustomerState {
constructor() { }
@Action(ChangeCustomerSuccess)
changeCustomerSuccess({ getState, setState }: StateContext<Customer>, { payload }: ChangeCustomerSuccess ) {
const state = getState();
// Set the new state. No service logic here.
setState( {
...state,
firstname: payload.firstname, lastname: lastname.nachname
});
}
}
次に、その状態から派生し、派生クラスにサービスロジックを配置します。
@State<Customer>({
name: 'customer'
})
export class CustomerServiceState extends CustomerState {
constructor(private customerService: CustomerService, private store: Store) {
super();
}
@Action(ChangeCustomerAction)
changeCustomerService({ getState, setState }: StateContext<Customer>, { payload }: ChangeCustomerAction) {
// This action does not need to change the state, but it can, e.g. to set the loading flag.
// It executes the (backend) effect and sends success / error to the store.
this.store.dispatch( new ChangeCustomerSuccess( payload ));
}
}
私が調べたNGXSの例では、このアプローチを見たことはありませんが、UIとバックエンドという2つの懸念事項を分離する方法を探していました。