21

我刚刚开始尝试,ngxs但从我目前的阅读来看,我并没有 100% 清楚我应该在哪里回调我的 API 以保存和读取数据(我见过的所有示例要么不这样做,要么使用一些模拟)。

例如,我创建了一个维护项目列表的状态。当我想添加一个项目时,我将“AddItem”操作发送到商店,在那里我将该新项目添加到状态。这一切正常 - 问题是插入将项目发布到服务器的调用的合适位置在哪里?

我是否应该在我的操作实现中调用 API,即在我更新商店的项目列表之前。

或者我应该在我的 Angular 组件中调用 API(通过服务),然后在收到响应时调度“添加项目”操作?

我对这个领域很陌生,所以这些方法的任何指导或优点/缺点都会很棒。

4

2 回答 2

20

最好的地方是在你的动作处理程序中。

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操作响应改变状态。

如果您愿意,可以将其拆分为三个更明确的操作,

AddTodo,AddTodoCompleteAddTodoFailure

在这种情况下,您需要从 http 帖子中发送新事件。

于 2018-04-23T07:21:13.457 回答
4

如果您想将效果与商店分开,您可以定义一个基本状态类:

@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 和后端。

于 2018-04-24T14:08:57.187 回答