Actions/state 从后端加载数据
Actions/state to load data from backend
我刚刚开始尝试 ngxs
,但从我目前的阅读来看,我并不是 100% 清楚我应该在哪里回调我的 API 来持久化和读取数据(我见过的所有例子要么不这样做,要么使用一些模拟)。
例如我创建了一个状态,用于维护项目列表。当我想添加一个项目时,我将“AddItem”操作分派到商店,我在商店中将该新项目添加到状态。这一切都正常 - 问题是插入将项目发布到服务器的调用的适当位置在哪里?
我是否应该在我的操作实现中调用 API,即在我更新商店的商品列表之前。
或者我是否应该在我的 Angular 组件中调用 API(通过服务),然后在我收到响应时发送 'Add Item' 操作?
我对这个领域还很陌生,所以任何指导或 pros/cons 这些方法都会很棒。
最好的地方是在您的操作处理程序中。
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 的 return 的显式操作,我们根据 AddTodo
操作响应来改变状态。
如果您愿意,可以将其拆分为三个操作以更明确,
AddTodo
、AddTodoComplete
和 AddTodoFailure
在这种情况下,您需要从 http post.
发送新事件
如果您想将效果与商店分开,您可以定义一个基本状态 class:
@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
});
}
}
然后您将从该状态派生并将您的服务逻辑放入派生的 class:
@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 和后端。
我刚刚开始尝试 ngxs
,但从我目前的阅读来看,我并不是 100% 清楚我应该在哪里回调我的 API 来持久化和读取数据(我见过的所有例子要么不这样做,要么使用一些模拟)。
例如我创建了一个状态,用于维护项目列表。当我想添加一个项目时,我将“AddItem”操作分派到商店,我在商店中将该新项目添加到状态。这一切都正常 - 问题是插入将项目发布到服务器的调用的适当位置在哪里?
我是否应该在我的操作实现中调用 API,即在我更新商店的商品列表之前。
或者我是否应该在我的 Angular 组件中调用 API(通过服务),然后在我收到响应时发送 'Add Item' 操作?
我对这个领域还很陌生,所以任何指导或 pros/cons 这些方法都会很棒。
最好的地方是在您的操作处理程序中。
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 的 return 的显式操作,我们根据 AddTodo
操作响应来改变状态。
如果您愿意,可以将其拆分为三个操作以更明确,
AddTodo
、AddTodoComplete
和 AddTodoFailure
在这种情况下,您需要从 http post.
发送新事件如果您想将效果与商店分开,您可以定义一个基本状态 class:
@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
});
}
}
然后您将从该状态派生并将您的服务逻辑放入派生的 class:
@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 和后端。